From 1b447137b0e2162e74a3894b1942ac3bc5a683f5 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 12 Jun 2019 11:40:10 -0700 Subject: [PATCH 01/36] HW-52585 UI - Receipt Details --- .../android/common/view/OneClickListener.java | 31 ++ .../common/viewmodel/ListDetailNavigator.java | 30 +- receipt/build.gradle | 6 +- receipt/src/main/AndroidManifest.xml | 14 +- .../receipt/view/ListReceiptActivity.java | 21 +- .../receipt/view/ListReceiptFragment.java | 85 +--- .../receipt/view/ReceiptDetailActivity.java | 72 +++ .../receipt/view/ReceiptDetailFragment.java | 134 ++++++ .../android/receipt/view/ReceiptViewUtil.java | 86 ++++ .../viewmodel/ListReceiptViewModel.java | 9 + .../viewmodel/ReceiptDetailViewModel.java | 34 ++ .../res/layout/activity_receipt_detail.xml | 18 + ...fragment.xml => fragment_list_receipt.xml} | 0 .../res/layout/fragment_receipt_detail.xml | 431 ++++++++++++++++++ receipt/src/main/res/layout/item_receipt.xml | 68 +-- .../res/layout/item_receipt_with_header.xml | 9 +- receipt/src/main/res/layout/receipt.xml | 69 +++ receipt/src/main/res/values/dimens.xml | 1 + receipt/src/main/res/values/strings.xml | 17 + .../ListTransferMethodActivity.java | 2 +- .../ListTransferMethodFragment.java | 2 +- .../SelectTransferMethodFragment.java | 2 +- 22 files changed, 981 insertions(+), 160 deletions(-) create mode 100644 common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java rename ui/src/main/java/com/hyperwallet/android/ui/view/widget/OneClickListener.java => common/src/main/java/com/hyperwallet/android/common/viewmodel/ListDetailNavigator.java (52%) create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailActivity.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ReceiptDetailViewModel.java create mode 100644 receipt/src/main/res/layout/activity_receipt_detail.xml rename receipt/src/main/res/layout/{list_receipt_fragment.xml => fragment_list_receipt.xml} (100%) create mode 100644 receipt/src/main/res/layout/fragment_receipt_detail.xml create mode 100644 receipt/src/main/res/layout/receipt.xml diff --git a/common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java b/common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java new file mode 100644 index 000000000..4ac3cbcf6 --- /dev/null +++ b/common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java @@ -0,0 +1,31 @@ +package com.hyperwallet.android.common.view; + +import android.os.SystemClock; +import android.view.View; + +/** + * Helper class that holds a time of the first click event and won't call onClick callback during a delay. + */ +public abstract class OneClickListener implements View.OnClickListener { + private static final long CLICK_DELAY_MILLIS = 800L; + private long mFirstOccurrenceClickTime; + + @Override + public void onClick(View v) { + if (SystemClock.elapsedRealtime() - mFirstOccurrenceClickTime < CLICK_DELAY_MILLIS) { + return; + } + + onOneClick(v); + mFirstOccurrenceClickTime = SystemClock.elapsedRealtime(); + + } + + /** + * Handle click events with a delay. This callback is time aware and will not appear the second time during a delay. + * + * @param v View + */ + public abstract void onOneClick(View v); +} + diff --git a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/OneClickListener.java b/common/src/main/java/com/hyperwallet/android/common/viewmodel/ListDetailNavigator.java similarity index 52% rename from ui/src/main/java/com/hyperwallet/android/ui/view/widget/OneClickListener.java rename to common/src/main/java/com/hyperwallet/android/common/viewmodel/ListDetailNavigator.java index 33e575c31..dd31e03ad 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/view/widget/OneClickListener.java +++ b/common/src/main/java/com/hyperwallet/android/common/viewmodel/ListDetailNavigator.java @@ -1,6 +1,6 @@ /* * The MIT License (MIT) - * Copyright (c) 2018 Hyperwallet Systems Inc. + * 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, @@ -14,33 +14,17 @@ * 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.widget; - -import android.os.SystemClock; -import android.view.View; +package com.hyperwallet.android.common.viewmodel; /** - * Helper class that holds a time of the first click event and won't call onClick callback during a delay. + * Detail interface for having a list UI with detail information through navigation */ -public abstract class OneClickListener implements View.OnClickListener { - private static final long CLICK_DELAY_MILLIS = 800L; - private long mFirstOccurrenceClickTime; - - @Override - public void onClick(View v) { - if (SystemClock.elapsedRealtime() - mFirstOccurrenceClickTime < CLICK_DELAY_MILLIS) { - return; - } - - onOneClick(v); - mFirstOccurrenceClickTime = SystemClock.elapsedRealtime(); - - } +public interface ListDetailNavigator { /** - * Handle click events with a delay. This callback is time aware and will not appear the second time during a delay. + * Navigate action * - * @param v View + * @param e Navigation event */ - public abstract void onOneClick(View v); + void navigate(Event e); } diff --git a/receipt/build.gradle b/receipt/build.gradle index 6aa8d9d42..3e8b31635 100644 --- a/receipt/build.gradle +++ b/receipt/build.gradle @@ -10,6 +10,10 @@ dependencies { implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion" implementation "androidx.paging:paging-runtime:$pagingRuntimeVersion" + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'com.google.android.material:material:1.0.0' testImplementation "org.robolectric:robolectric:$robolectricVersion" androidTestImplementation "androidx.test:rules:$testRulesVersion" @@ -108,4 +112,4 @@ sonarqube { property "sonar.libraries", libraries property "sonar.projectName", "android-ui-sdk-receipt" } -} \ No newline at end of file +} diff --git a/receipt/src/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index 3039f6d18..2d5260645 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -1,13 +1,19 @@ - - + + + + \ No newline at end of file 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 index e7f57c821..597d38296 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptActivity.java @@ -33,15 +33,18 @@ 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.common.viewmodel.ListDetailNavigator; import com.hyperwallet.android.model.HyperwalletError; import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; 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 { +public class ListReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback, + ListDetailNavigator> { private ListReceiptViewModel mListReceiptViewModel; @@ -76,6 +79,13 @@ public void onChanged(Event event) { } }); + mListReceiptViewModel.getDetailNavigation().observe(this, new Observer>() { + @Override + public void onChanged(Event event) { + navigate(event); + } + }); + if (savedInstanceState == null) { initFragment(ListReceiptFragment.newInstance()); } @@ -130,4 +140,13 @@ private void showErrorOnLoadReceipt(@NonNull final List errors fragment.show(fragmentManager); } } + + @Override + public void navigate(@NonNull final Event event) { + if (!event.isContentConsumed()) { + Intent intent = new Intent(this, ReceiptDetailActivity.class); + intent.putExtra(ReceiptDetailActivity.EXTRA_RECEIPT, event.getContent()); + startActivity(intent); + } + } } 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 index ce6f9fd4d..fa671f4a5 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java @@ -16,10 +16,6 @@ */ 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; @@ -38,12 +34,12 @@ import androidx.recyclerview.widget.RecyclerView; import com.hyperwallet.android.common.util.DateUtils; +import com.hyperwallet.android.common.view.OneClickListener; 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 { @@ -77,14 +73,14 @@ public void onCreate(@Nullable final Bundle savedInstanceState) { @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); + return inflater.inflate(R.layout.fragment_list_receipt, 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()); + mListReceiptAdapter = new ListReceiptAdapter(mListReceiptViewModel, new ListReceiptItemDiffCallback()); mListReceiptsView = view.findViewById(R.id.list_receipts); mListReceiptsView.setHasFixedSize(true); mListReceiptsView.setLayoutManager(new LinearLayoutManager(getActivity())); @@ -136,12 +132,14 @@ 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; + private final ListReceiptViewModel mReceiptViewModel; - ListReceiptAdapter(@NonNull final DiffUtil.ItemCallback diffCallback) { + ListReceiptAdapter(@NonNull final ListReceiptViewModel receiptViewModel, + @NonNull final DiffUtil.ItemCallback diffCallback) { super(diffCallback); + mReceiptViewModel = receiptViewModel; } @Override @@ -173,10 +171,10 @@ public ReceiptViewHolder onCreateViewHolder(final @NonNull ViewGroup viewGroup, if (viewType == HEADER_VIEW_TYPE) { View headerView = layout.inflate(R.layout.item_receipt_with_header, viewGroup, false); - return new ReceiptViewHolderWithHeader(headerView); + return new ReceiptViewHolderWithHeader(mReceiptViewModel, headerView); } View dataView = layout.inflate(R.layout.item_receipt, viewGroup, false); - return new ReceiptViewHolder(dataView); + return new ReceiptViewHolder(mReceiptViewModel, dataView); } @Override @@ -188,59 +186,23 @@ public void onBindViewHolder(@NonNull final ReceiptViewHolder holder, final int } 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) { + private ListReceiptViewModel mListReceiptViewModel; + + ReceiptViewHolder(@NonNull final ListReceiptViewModel receiptViewModel, + @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); + mListReceiptViewModel = receiptViewModel; } 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; + ReceiptViewUtil.setTransactionView(receipt, itemView); + itemView.setOnClickListener(new OneClickListener() { + @Override + public void onOneClick(View v) { + mListReceiptViewModel.setDetailNavigation(receipt); + } + }); } } @@ -248,8 +210,9 @@ class ReceiptViewHolderWithHeader extends ReceiptViewHolder { private final TextView mTransactionHeaderText; - ReceiptViewHolderWithHeader(@NonNull final View item) { - super(item); + ReceiptViewHolderWithHeader(@NonNull final ListReceiptViewModel receiptViewModel, + @NonNull final View item) { + super(receiptViewModel, item); mTransactionHeaderText = item.findViewById(R.id.item_date_header_title); } diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailActivity.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailActivity.java new file mode 100644 index 000000000..74641b76f --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailActivity.java @@ -0,0 +1,72 @@ +/* + * 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.os.Bundle; +import android.os.Parcelable; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.ViewModelProviders; + +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.receipt.R; +import com.hyperwallet.android.receipt.viewmodel.ReceiptDetailViewModel; + +public class ReceiptDetailActivity extends AppCompatActivity { + + public static final String EXTRA_RECEIPT = "RECEIPT"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_receipt_detail); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + getSupportActionBar().setTitle(R.string.title_activity_receipt_detail); + + Parcelable parcel = getIntent().getParcelableExtra(EXTRA_RECEIPT); + if (parcel instanceof Receipt) { + ReceiptDetailViewModel viewModel = ViewModelProviders.of(this).get(ReceiptDetailViewModel.class); + viewModel.setReceipt((Receipt) parcel); + } else { + throw new IllegalArgumentException("Cannot initialize " + ReceiptDetailActivity.class.getName() + + " " + EXTRA_RECEIPT + " argument is not as what is expected."); + } + + if (savedInstanceState == null) { + initFragment(ReceiptDetailFragment.newInstance()); + } + } + + private void initFragment(@NonNull final Fragment fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.add(R.id.receipt_detail_fragment, fragment); + fragmentTransaction.commit(); + } + + @Override + public boolean onSupportNavigateUp() { + onBackPressed(); + return true; + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java new file mode 100644 index 000000000..4719588f0 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java @@ -0,0 +1,134 @@ +/* + * 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.os.Bundle; +import android.text.TextUtils; +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.ViewModelProviders; + +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.ReceiptDetailViewModel; + +import java.text.DecimalFormat; + +public class ReceiptDetailFragment extends Fragment { + + private static final String DETAIL_DATE_FORMAT = "E MMM dd YYYY - k:mm z"; + private static final String AMOUNT_FORMAT = "#,##0.00"; + private ReceiptDetailViewModel mReceiptDetailViewModel; + + public ReceiptDetailFragment() { + setRetainInstance(true); + } + + public static ReceiptDetailFragment newInstance() { + ReceiptDetailFragment fragment = new ReceiptDetailFragment(); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mReceiptDetailViewModel = ViewModelProviders.of(requireActivity()).get(ReceiptDetailViewModel.class); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_receipt_detail, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + Receipt receipt = mReceiptDetailViewModel.getReceipt(); + + // transactions + ReceiptViewUtil.setTransactionView(receipt, view); + + // fee details + if (!TextUtils.isEmpty(receipt.getFee())) { + view.findViewById(R.id.fee_details_layout).setVisibility(View.VISIBLE); + double feeAmount = Double.parseDouble(receipt.getFee()); + double transferAmount = Double.parseDouble(receipt.getAmount()); + double amount = transferAmount - feeAmount; + DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); + + TextView amountView = view.findViewById(R.id.details_amount_value); + amountView.setText(view.getContext().getString(R.string.amount_view_format, + decimalFormat.format(amount), receipt.getCurrency())); + + TextView fee = view.findViewById(R.id.details_fee_value); + fee.setText(view.getContext().getString(R.string.amount_view_format, + decimalFormat.format(feeAmount), receipt.getCurrency())); + + TextView transfer = view.findViewById(R.id.details_transfer_amount_value); + transfer.setText(view.getContext().getString(R.string.amount_view_format, + decimalFormat.format(transferAmount), receipt.getCurrency())); + } + + // receipt details + TextView receiptId = view.findViewById(R.id.receipt_id_value); + receiptId.setText(receipt.getJournalId()); + TextView date = view.findViewById(R.id.date_value); + date.setText(DateUtils.toDateFormat(DateUtils. + fromDateTimeString(receipt.getCreatedOn()), DETAIL_DATE_FORMAT)); + + if (receipt.getDetails() != null) { + if (!TextUtils.isEmpty(receipt.getDetails().getCharityName())) { + view.findViewById(R.id.charity_layout).setVisibility(View.VISIBLE); + TextView charity = view.findViewById(R.id.charity_value); + charity.setText(receipt.getDetails().getCharityName()); + } + + if (!TextUtils.isEmpty(receipt.getDetails().getCheckNumber())) { + view.findViewById(R.id.check_number_layout).setVisibility(View.VISIBLE); + TextView check = view.findViewById(R.id.check_number_value); + check.setText(receipt.getDetails().getCheckNumber()); + } + + if (!TextUtils.isEmpty(receipt.getDetails().getClientPaymentId())) { + view.findViewById(R.id.client_id_layout).setVisibility(View.VISIBLE); + TextView client = view.findViewById(R.id.client_id_value); + client.setText(receipt.getDetails().getClientPaymentId()); + } + + if (!TextUtils.isEmpty(receipt.getDetails().getNotes())) { + view.findViewById(R.id.notes_layout).setVisibility(View.VISIBLE); + TextView notes = view.findViewById(R.id.notes_value); + notes.setText(receipt.getDetails().getNotes()); + } + + if (!TextUtils.isEmpty(receipt.getDetails().getWebsite())) { + view.findViewById(R.id.website_layout).setVisibility(View.VISIBLE); + TextView website = view.findViewById(R.id.notes_value); + website.setText(receipt.getDetails().getWebsite()); + } + } + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java new file mode 100644 index 000000000..ca7bdabf6 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java @@ -0,0 +1,86 @@ +/* + * 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.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.hyperwallet.android.common.util.DateUtils; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.receipt.R; + +import java.util.Locale; + +final class ReceiptViewUtil { + + private static final String CAPTION_DATE_FORMAT = "MMMM dd, yyyy"; + + private ReceiptViewUtil() { + } + + static void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { + TextView transactionTypeIcon = view.findViewById(R.id.transaction_type_icon); + TextView transactionTitle = view.findViewById(R.id.transaction_title); + TextView transactionDate = view.findViewById(R.id.transaction_date); + TextView transactionAmount = view.findViewById(R.id.transaction_amount); + TextView transactionCurrency = view.findViewById(R.id.transaction_currency); + + if (CREDIT.equals(receipt.getEntry())) { + transactionAmount.setTextColor(transactionAmount.getContext() + .getResources().getColor(R.color.positiveColor)); + transactionAmount.setText(transactionAmount.getContext() + .getString(R.string.credit_sign, receipt.getAmount())); + transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() + .getResources().getColor(R.color.positiveColor)); + transactionTypeIcon.setBackground(transactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_positive)); + transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.credit)); + } else if (DEBIT.equals(receipt.getEntry())) { + transactionAmount.setTextColor(transactionAmount.getContext() + .getResources().getColor(R.color.colorAccent)); + transactionAmount.setText(transactionAmount.getContext() + .getString(R.string.debit_sign, receipt.getAmount())); + transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() + .getResources().getColor(R.color.colorAccent)); + transactionTypeIcon.setBackground(transactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_negative)); + transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.debit)); + } + + transactionCurrency.setText(receipt.getCurrency()); + transactionTitle.setText(getTransactionTitle(receipt.getType(), transactionTitle.getContext())); + transactionDate.setText(DateUtils.toDateFormat(DateUtils. + fromDateTimeString(receipt.getCreatedOn()), CAPTION_DATE_FORMAT)); + } + + private static 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; + } +} 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 index 57f41b5c1..612a8ae59 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ListReceiptViewModel.java @@ -32,6 +32,7 @@ public class ListReceiptViewModel extends ViewModel { private MutableLiveData> mErrorEvent = new MutableLiveData<>(); + private MutableLiveData> mDetailNavigation = new MutableLiveData<>(); private Observer> mErrorEventObserver; private ReceiptRepository mReceiptRepository; @@ -66,6 +67,14 @@ public void retryLoadReceipts() { mReceiptRepository.retryLoadReceipt(); } + public LiveData> getDetailNavigation() { + return mDetailNavigation; + } + + public void setDetailNavigation(@NonNull final Receipt receipt) { + mDetailNavigation.postValue(new Event<>(receipt)); + } + @Override protected void onCleared() { super.onCleared(); diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ReceiptDetailViewModel.java b/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ReceiptDetailViewModel.java new file mode 100644 index 000000000..23d937e27 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/viewmodel/ReceiptDetailViewModel.java @@ -0,0 +1,34 @@ +/* + * 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.lifecycle.ViewModel; + +import com.hyperwallet.android.model.receipt.Receipt; + +public class ReceiptDetailViewModel extends ViewModel { + + private Receipt mReceipt; + + public Receipt getReceipt() { + return mReceipt; + } + + public void setReceipt(Receipt receipt) { + mReceipt = receipt; + } +} diff --git a/receipt/src/main/res/layout/activity_receipt_detail.xml b/receipt/src/main/res/layout/activity_receipt_detail.xml new file mode 100644 index 000000000..f59621173 --- /dev/null +++ b/receipt/src/main/res/layout/activity_receipt_detail.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/receipt/src/main/res/layout/list_receipt_fragment.xml b/receipt/src/main/res/layout/fragment_list_receipt.xml similarity index 100% rename from receipt/src/main/res/layout/list_receipt_fragment.xml rename to receipt/src/main/res/layout/fragment_list_receipt.xml diff --git a/receipt/src/main/res/layout/fragment_receipt_detail.xml b/receipt/src/main/res/layout/fragment_receipt_detail.xml new file mode 100644 index 000000000..8d1fb183b --- /dev/null +++ b/receipt/src/main/res/layout/fragment_receipt_detail.xml @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 index 4388d4ab7..9d30c3fee 100644 --- a/receipt/src/main/res/layout/item_receipt.xml +++ b/receipt/src/main/res/layout/item_receipt.xml @@ -1,73 +1,9 @@ - - - - - - - - - - + \ 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 index 29f002169..4b7e57253 100644 --- a/receipt/src/main/res/layout/item_receipt_with_header.xml +++ b/receipt/src/main/res/layout/item_receipt_with_header.xml @@ -21,6 +21,13 @@ android:textAppearance="@style/TextAppearance.Hyperwallet.Body2"/> - + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/layout/receipt.xml b/receipt/src/main/res/layout/receipt.xml new file mode 100644 index 000000000..db8ab28da --- /dev/null +++ b/receipt/src/main/res/layout/receipt.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/values/dimens.xml b/receipt/src/main/res/values/dimens.xml index 999d990b2..328889b96 100644 --- a/receipt/src/main/res/values/dimens.xml +++ b/receipt/src/main/res/values/dimens.xml @@ -3,4 +3,5 @@ 10dp 8dp 70dp + 16dp diff --git a/receipt/src/main/res/values/strings.xml b/receipt/src/main/res/values/strings.xml index 6c6730a9e..e0022a543 100644 --- a/receipt/src/main/res/values/strings.xml +++ b/receipt/src/main/res/values/strings.xml @@ -1,6 +1,22 @@ receipt Transactions + Transaction Details + Transaction + Details + Amount: + Fee: + Transfer Amount: + Receipt + Receipt ID: + Date: + Client ID: + Notes: + Charity Name: + Check Number: + Website: + %s %s + Seems like, you don\'t have any Transactions, yet. @@ -115,4 +131,5 @@ Wire Transfer Wire Transfer Fee Wire Transfer Return + MainActivity 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..0f29c1df3 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,12 +30,12 @@ import androidx.fragment.app.FragmentTransaction; import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.hyperwallet.android.common.view.OneClickListener; 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.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 d09829047..fe1949269 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 @@ -49,13 +49,13 @@ import androidx.recyclerview.widget.RecyclerView; import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; +import com.hyperwallet.android.common.view.OneClickListener; 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.widget.OneClickListener; import java.util.ArrayList; import java.util.List; 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..aac497695 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 @@ -39,12 +39,12 @@ import androidx.recyclerview.widget.RecyclerView; import com.hyperwallet.android.common.view.HorizontalDividerItemDecorator; +import com.hyperwallet.android.common.view.OneClickListener; 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.widget.OneClickListener; import java.util.ArrayList; import java.util.List; From 6f222bdf8fbf82c7492f7495a304fe68c3f13dcb Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 12 Jun 2019 11:56:01 -0700 Subject: [PATCH 02/36] remove unnecessary configs --- .../android/common/view/OneClickListener.java | 16 ++++++++++++++++ receipt/build.gradle | 4 ---- receipt/config/lint.xml | 3 +++ receipt/src/main/AndroidManifest.xml | 7 +++++-- .../receipt/view/ReceiptDetailActivity.java | 10 ++++++++++ .../main/res/layout/activity_receipt_detail.xml | 14 ++++++++++++++ receipt/src/main/res/values/dimens.xml | 1 - receipt/src/main/res/values/strings.xml | 1 - 8 files changed, 48 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java b/common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java index 4ac3cbcf6..f244cb244 100644 --- a/common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java +++ b/common/src/main/java/com/hyperwallet/android/common/view/OneClickListener.java @@ -1,3 +1,19 @@ +/* + * 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.view; import android.os.SystemClock; diff --git a/receipt/build.gradle b/receipt/build.gradle index 3e8b31635..a25d0e955 100644 --- a/receipt/build.gradle +++ b/receipt/build.gradle @@ -10,10 +10,6 @@ dependencies { implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion" implementation "androidx.paging:paging-runtime:$pagingRuntimeVersion" - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'com.google.android.material:material:1.0.0' testImplementation "org.robolectric:robolectric:$robolectricVersion" androidTestImplementation "androidx.test:rules:$testRulesVersion" diff --git a/receipt/config/lint.xml b/receipt/config/lint.xml index 3c83d4bb5..ff446fa9e 100644 --- a/receipt/config/lint.xml +++ b/receipt/config/lint.xml @@ -4,4 +4,7 @@ + + + \ No newline at end of file diff --git a/receipt/src/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index 2d5260645..bc6466bb8 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -8,8 +8,11 @@ - - + + + + + + + + + 10dp 8dp 70dp - 16dp diff --git a/receipt/src/main/res/values/strings.xml b/receipt/src/main/res/values/strings.xml index e0022a543..d6b595c3b 100644 --- a/receipt/src/main/res/values/strings.xml +++ b/receipt/src/main/res/values/strings.xml @@ -131,5 +131,4 @@ Wire Transfer Wire Transfer Fee Wire Transfer Return - MainActivity From 4d879811a436b07286082c56621ff0b97fc4f110 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 12 Jun 2019 14:51:57 -0700 Subject: [PATCH 03/36] formatted amounts --- .../android/receipt/view/ListReceiptFragment.java | 7 +++++-- .../receipt/view/ReceiptDetailFragment.java | 8 +++++--- .../android/receipt/view/ReceiptViewUtil.java | 15 +++++++++------ receipt/src/main/res/layout/item_receipt.xml | 1 + .../main/res/layout/item_receipt_with_header.xml | 1 + 5 files changed, 21 insertions(+), 11 deletions(-) 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 index fa671f4a5..a1de5414e 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java @@ -188,16 +188,19 @@ public void onBindViewHolder(@NonNull final ReceiptViewHolder holder, final int class ReceiptViewHolder extends RecyclerView.ViewHolder { private ListReceiptViewModel mListReceiptViewModel; + private View mView; ReceiptViewHolder(@NonNull final ListReceiptViewModel receiptViewModel, @NonNull final View item) { super(item); + mView = item.findViewById(R.id.receipt_item); mListReceiptViewModel = receiptViewModel; } void bind(@NonNull final Receipt receipt) { - ReceiptViewUtil.setTransactionView(receipt, itemView); - itemView.setOnClickListener(new OneClickListener() { + ReceiptViewUtil util = new ReceiptViewUtil(); + util.setTransactionView(receipt, itemView); + mView.setOnClickListener(new OneClickListener() { @Override public void onOneClick(View v) { mListReceiptViewModel.setDetailNavigation(receipt); diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java index 4719588f0..1c540e48e 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java @@ -16,6 +16,9 @@ */ package com.hyperwallet.android.receipt.view; +import static com.hyperwallet.android.receipt.view.ReceiptViewUtil.AMOUNT_FORMAT; +import static com.hyperwallet.android.receipt.view.ReceiptViewUtil.DETAIL_DATE_FORMAT; + import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; @@ -37,8 +40,6 @@ public class ReceiptDetailFragment extends Fragment { - private static final String DETAIL_DATE_FORMAT = "E MMM dd YYYY - k:mm z"; - private static final String AMOUNT_FORMAT = "#,##0.00"; private ReceiptDetailViewModel mReceiptDetailViewModel; public ReceiptDetailFragment() { @@ -69,7 +70,8 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat Receipt receipt = mReceiptDetailViewModel.getReceipt(); // transactions - ReceiptViewUtil.setTransactionView(receipt, view); + ReceiptViewUtil util = new ReceiptViewUtil(); + util.setTransactionView(receipt, view); // fee details if (!TextUtils.isEmpty(receipt.getFee())) { diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java index ca7bdabf6..0bd7ed3ef 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java @@ -29,27 +29,30 @@ import com.hyperwallet.android.model.receipt.Receipt; import com.hyperwallet.android.receipt.R; +import java.text.DecimalFormat; import java.util.Locale; final class ReceiptViewUtil { + static final String DETAIL_DATE_FORMAT = "E MMM dd, YYYY - k:mm zzz"; + static final String AMOUNT_FORMAT = "#,##0.00"; private static final String CAPTION_DATE_FORMAT = "MMMM dd, yyyy"; - private ReceiptViewUtil() { - } - - static void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { + void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { TextView transactionTypeIcon = view.findViewById(R.id.transaction_type_icon); TextView transactionTitle = view.findViewById(R.id.transaction_title); TextView transactionDate = view.findViewById(R.id.transaction_date); TextView transactionAmount = view.findViewById(R.id.transaction_amount); TextView transactionCurrency = view.findViewById(R.id.transaction_currency); + DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); + double amount = Double.parseDouble(receipt.getAmount()); + String formattedAmount = decimalFormat.format(amount); if (CREDIT.equals(receipt.getEntry())) { transactionAmount.setTextColor(transactionAmount.getContext() .getResources().getColor(R.color.positiveColor)); transactionAmount.setText(transactionAmount.getContext() - .getString(R.string.credit_sign, receipt.getAmount())); + .getString(R.string.credit_sign, formattedAmount)); transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() .getResources().getColor(R.color.positiveColor)); transactionTypeIcon.setBackground(transactionTypeIcon.getContext() @@ -59,7 +62,7 @@ static void setTransactionView(@NonNull final Receipt receipt, @NonNull final Vi transactionAmount.setTextColor(transactionAmount.getContext() .getResources().getColor(R.color.colorAccent)); transactionAmount.setText(transactionAmount.getContext() - .getString(R.string.debit_sign, receipt.getAmount())); + .getString(R.string.debit_sign, formattedAmount)); transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() .getResources().getColor(R.color.colorAccent)); transactionTypeIcon.setBackground(transactionTypeIcon.getContext() diff --git a/receipt/src/main/res/layout/item_receipt.xml b/receipt/src/main/res/layout/item_receipt.xml index 9d30c3fee..c30bba973 100644 --- a/receipt/src/main/res/layout/item_receipt.xml +++ b/receipt/src/main/res/layout/item_receipt.xml @@ -1,6 +1,7 @@ diff --git a/receipt/src/main/res/layout/item_receipt_with_header.xml b/receipt/src/main/res/layout/item_receipt_with_header.xml index 4b7e57253..9e5c72649 100644 --- a/receipt/src/main/res/layout/item_receipt_with_header.xml +++ b/receipt/src/main/res/layout/item_receipt_with_header.xml @@ -23,6 +23,7 @@ From 5ffbcb3dac30e8faf8e309073c9e150041026ec6 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 12 Jun 2019 15:12:49 -0700 Subject: [PATCH 04/36] remove static --- .../com/hyperwallet/android/receipt/view/ReceiptViewUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java index 0bd7ed3ef..9707915b8 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java @@ -76,7 +76,7 @@ void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view fromDateTimeString(receipt.getCreatedOn()), CAPTION_DATE_FORMAT)); } - private static String getTransactionTitle(@NonNull final String receiptType, @NonNull final Context context) { + 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()); From 30d585a4f8556aed24f804930ecf89a4e1c677ea Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 12 Jun 2019 15:15:44 -0700 Subject: [PATCH 05/36] fixed variable name --- .../hyperwallet/android/receipt/view/ListReceiptFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index a1de5414e..309f0a4b6 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ListReceiptFragment.java @@ -92,8 +92,8 @@ public void onViewCreated(@NonNull final View view, @Nullable final Bundle saved private void registerObservers() { mListReceiptViewModel.getReceiptList().observe(getViewLifecycleOwner(), new Observer>() { @Override - public void onChanged(PagedList transferMethods) { - mListReceiptAdapter.submitList(transferMethods); + public void onChanged(PagedList receipts) { + mListReceiptAdapter.submitList(receipts); } }); From c6926294b279f1992abe1ad1e6c07d312688d7e3 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Thu, 13 Jun 2019 08:53:50 -0700 Subject: [PATCH 06/36] refactored methods --- .../receipt/view/ReceiptDetailFragment.java | 45 ++++++++++--------- .../android/receipt/view/ReceiptViewUtil.java | 2 +- .../res/layout/fragment_receipt_detail.xml | 13 ------ 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java index 1c540e48e..0c2e719ec 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java @@ -26,6 +26,7 @@ import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; @@ -33,6 +34,7 @@ import com.hyperwallet.android.common.util.DateUtils; import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.model.receipt.ReceiptDetails; import com.hyperwallet.android.receipt.R; import com.hyperwallet.android.receipt.viewmodel.ReceiptDetailViewModel; @@ -102,35 +104,38 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat fromDateTimeString(receipt.getCreatedOn()), DETAIL_DATE_FORMAT)); if (receipt.getDetails() != null) { - if (!TextUtils.isEmpty(receipt.getDetails().getCharityName())) { - view.findViewById(R.id.charity_layout).setVisibility(View.VISIBLE); - TextView charity = view.findViewById(R.id.charity_value); - charity.setText(receipt.getDetails().getCharityName()); + ReceiptDetails receiptDetails = receipt.getDetails(); + if (!TextUtils.isEmpty(receiptDetails.getCharityName())) { + setViewInformation(R.id.charity_layout, R.id.charity_value, + view, receiptDetails.getCharityName()); } - if (!TextUtils.isEmpty(receipt.getDetails().getCheckNumber())) { - view.findViewById(R.id.check_number_layout).setVisibility(View.VISIBLE); - TextView check = view.findViewById(R.id.check_number_value); - check.setText(receipt.getDetails().getCheckNumber()); + if (!TextUtils.isEmpty(receiptDetails.getCheckNumber())) { + setViewInformation(R.id.check_number_layout, R.id.check_number_value, + view, receiptDetails.getCheckNumber()); } - if (!TextUtils.isEmpty(receipt.getDetails().getClientPaymentId())) { - view.findViewById(R.id.client_id_layout).setVisibility(View.VISIBLE); - TextView client = view.findViewById(R.id.client_id_value); - client.setText(receipt.getDetails().getClientPaymentId()); + if (!TextUtils.isEmpty(receiptDetails.getClientPaymentId())) { + setViewInformation(R.id.client_id_layout, R.id.client_id_value, + view, receiptDetails.getClientPaymentId()); } - if (!TextUtils.isEmpty(receipt.getDetails().getNotes())) { - view.findViewById(R.id.notes_layout).setVisibility(View.VISIBLE); - TextView notes = view.findViewById(R.id.notes_value); - notes.setText(receipt.getDetails().getNotes()); + if (!TextUtils.isEmpty(receiptDetails.getNotes())) { + setViewInformation(R.id.notes_layout, R.id.notes_value, + view, receiptDetails.getNotes()); } - if (!TextUtils.isEmpty(receipt.getDetails().getWebsite())) { - view.findViewById(R.id.website_layout).setVisibility(View.VISIBLE); - TextView website = view.findViewById(R.id.notes_value); - website.setText(receipt.getDetails().getWebsite()); + if (!TextUtils.isEmpty(receiptDetails.getWebsite())) { + setViewInformation(R.id.website_layout, R.id.website_value, + view, receiptDetails.getWebsite()); } } } + + private void setViewInformation(@IdRes final int layout, @IdRes final int viewValue, + @NonNull final View view, @NonNull final String value) { + view.findViewById(layout).setVisibility(View.VISIBLE); + TextView textView = view.findViewById(viewValue); + textView.setText(value); + } } diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java index 9707915b8..2048d1401 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java @@ -35,7 +35,7 @@ final class ReceiptViewUtil { static final String DETAIL_DATE_FORMAT = "E MMM dd, YYYY - k:mm zzz"; - static final String AMOUNT_FORMAT = "#,##0.00"; + static final String AMOUNT_FORMAT = "###0.00"; private static final String CAPTION_DATE_FORMAT = "MMMM dd, yyyy"; void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { diff --git a/receipt/src/main/res/layout/fragment_receipt_detail.xml b/receipt/src/main/res/layout/fragment_receipt_detail.xml index 8d1fb183b..79aafab7d 100644 --- a/receipt/src/main/res/layout/fragment_receipt_detail.xml +++ b/receipt/src/main/res/layout/fragment_receipt_detail.xml @@ -415,17 +415,4 @@ - - - - - - - - - - - - - \ No newline at end of file From 8987e718d5338b76f05724d55923f304c121c6df Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Fri, 14 Jun 2019 07:53:36 -0700 Subject: [PATCH 07/36] added 12-HR to 24-HR and vice-versa formatter --- .../android/receipt/view/ReceiptDetailFragment.java | 8 ++++++-- .../hyperwallet/android/receipt/view/ReceiptViewUtil.java | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java index 0c2e719ec..df87097be 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java @@ -17,10 +17,12 @@ package com.hyperwallet.android.receipt.view; import static com.hyperwallet.android.receipt.view.ReceiptViewUtil.AMOUNT_FORMAT; -import static com.hyperwallet.android.receipt.view.ReceiptViewUtil.DETAIL_DATE_FORMAT; +import static com.hyperwallet.android.receipt.view.ReceiptViewUtil.DETAIL_DATE_TIME_12H_FORMAT; +import static com.hyperwallet.android.receipt.view.ReceiptViewUtil.DETAIL_DATE_TIME_24H_FORMAT; import android.os.Bundle; import android.text.TextUtils; +import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -101,7 +103,9 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat receiptId.setText(receipt.getJournalId()); TextView date = view.findViewById(R.id.date_value); date.setText(DateUtils.toDateFormat(DateUtils. - fromDateTimeString(receipt.getCreatedOn()), DETAIL_DATE_FORMAT)); + fromDateTimeString(receipt.getCreatedOn()), + DateFormat.is24HourFormat(view.getContext()) ? DETAIL_DATE_TIME_24H_FORMAT + : DETAIL_DATE_TIME_12H_FORMAT)); if (receipt.getDetails() != null) { ReceiptDetails receiptDetails = receipt.getDetails(); diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java index 2048d1401..57ff33a9f 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptViewUtil.java @@ -34,8 +34,9 @@ final class ReceiptViewUtil { - static final String DETAIL_DATE_FORMAT = "E MMM dd, YYYY - k:mm zzz"; static final String AMOUNT_FORMAT = "###0.00"; + static final String DETAIL_DATE_TIME_24H_FORMAT = "E MMM dd, YYYY - HH:mm zzz"; + static final String DETAIL_DATE_TIME_12H_FORMAT = "E MMM dd, YYYY - hh:mm a zzz"; private static final String CAPTION_DATE_FORMAT = "MMMM dd, yyyy"; void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { From 5c0030642938006d7d95ed81296d57c588416a94 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Fri, 14 Jun 2019 08:26:41 -0700 Subject: [PATCH 08/36] granular code {^__^} --- .../android/receipt/view/ReceiptDetailFragment.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java index df87097be..baec197ab 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java @@ -78,6 +78,13 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat util.setTransactionView(receipt, view); // fee details + setFeeDetailsView(receipt, view); + + // receipt details + setDetailsView(receipt, view); + } + + private void setFeeDetailsView(@NonNull final Receipt receipt, @NonNull final View view) { if (!TextUtils.isEmpty(receipt.getFee())) { view.findViewById(R.id.fee_details_layout).setVisibility(View.VISIBLE); double feeAmount = Double.parseDouble(receipt.getFee()); @@ -97,8 +104,9 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat transfer.setText(view.getContext().getString(R.string.amount_view_format, decimalFormat.format(transferAmount), receipt.getCurrency())); } + } - // receipt details + private void setDetailsView(@NonNull final Receipt receipt, @NonNull final View view) { TextView receiptId = view.findViewById(R.id.receipt_id_value); receiptId.setText(receipt.getJournalId()); TextView date = view.findViewById(R.id.date_value); From 1241fdc7167265e7a8fdac4000fa606629255298 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Fri, 14 Jun 2019 11:50:09 -0700 Subject: [PATCH 09/36] convention --- .../com/hyperwallet/android/common/viewmodel/Event.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 index a07aab0e1..35c21673a 100644 --- a/common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java +++ b/common/src/main/java/com/hyperwallet/android/common/viewmodel/Event.java @@ -24,11 +24,11 @@ */ public class Event { - private final T content; + private final T mContent; private boolean mIsContentConsumed; public Event(@NonNull final T t) { - content = t; + mContent = t; } /** @@ -38,7 +38,7 @@ public Event(@NonNull final T t) { @NonNull public T getContent() { mIsContentConsumed = true; - return content; + return mContent; } /** @@ -58,7 +58,7 @@ public boolean isContentConsumed() { public T getContentIfNotConsumed() { if (!mIsContentConsumed) { mIsContentConsumed = true; - return content; + return mContent; } return null; } From 8d9138a80647496b34f1a79ba5313440054428c8 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Fri, 14 Jun 2019 14:03:32 -0700 Subject: [PATCH 10/36] fix amount and transfer amount reversed --- .../android/receipt/view/ReceiptDetailFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java index baec197ab..20eee5fc5 100644 --- a/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/receipt/view/ReceiptDetailFragment.java @@ -88,8 +88,8 @@ private void setFeeDetailsView(@NonNull final Receipt receipt, @NonNull final Vi if (!TextUtils.isEmpty(receipt.getFee())) { view.findViewById(R.id.fee_details_layout).setVisibility(View.VISIBLE); double feeAmount = Double.parseDouble(receipt.getFee()); - double transferAmount = Double.parseDouble(receipt.getAmount()); - double amount = transferAmount - feeAmount; + double amount = Double.parseDouble(receipt.getAmount()); + double transferAmount = amount - feeAmount; DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); TextView amountView = view.findViewById(R.id.details_amount_value); From 465ecb9d822490702e1854d15d71199affec51ab Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Mon, 17 Jun 2019 08:48:36 -0700 Subject: [PATCH 11/36] fix date localization formatting to receipt views --- .../ui/receipt/view/ListReceiptFragment.java | 11 +++++-- .../receipt/view/ReceiptDetailFragment.java | 31 ++++++++++++------- .../ui/receipt/view/ReceiptViewUtil.java | 14 ++++++--- receipt/src/main/res/values/strings.xml | 2 +- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index 578e1ca65..1dce9c4ca 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -16,6 +16,11 @@ */ package com.hyperwallet.android.ui.receipt.view; +import static android.text.format.DateUtils.FORMAT_NO_MONTH_DAY; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.formatDateTime; + import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -40,6 +45,7 @@ import com.hyperwallet.android.ui.receipt.viewmodel.ListReceiptViewModel; import java.util.Calendar; +import java.util.Date; import java.util.Objects; public class ListReceiptFragment extends Fragment { @@ -222,8 +228,9 @@ class ReceiptViewHolderWithHeader extends ReceiptViewHolder { @Override void bind(@NonNull final Receipt receipt) { super.bind(receipt); - mTransactionHeaderText.setText(DateUtils.toDateFormat( - DateUtils.fromDateTimeString(receipt.getCreatedOn()), HEADER_DATE_FORMAT)); + Date date = DateUtils.fromDateTimeString(receipt.getCreatedOn()); + mTransactionHeaderText.setText(formatDateTime(mTransactionHeaderText.getContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_NO_MONTH_DAY)); } } } diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java index b2b13b92a..9b86ccd41 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java @@ -16,13 +16,18 @@ */ package com.hyperwallet.android.ui.receipt.view; +import static android.text.format.DateUtils.FORMAT_ABBREV_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_TIME; +import static android.text.format.DateUtils.FORMAT_SHOW_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.formatDateTime; + import static com.hyperwallet.android.ui.receipt.view.ReceiptViewUtil.AMOUNT_FORMAT; -import static com.hyperwallet.android.ui.receipt.view.ReceiptViewUtil.DETAIL_DATE_TIME_12H_FORMAT; -import static com.hyperwallet.android.ui.receipt.view.ReceiptViewUtil.DETAIL_DATE_TIME_24H_FORMAT; +import static com.hyperwallet.android.ui.receipt.view.ReceiptViewUtil.DETAIL_TIMEZONE; import android.os.Bundle; import android.text.TextUtils; -import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -41,6 +46,7 @@ import com.hyperwallet.android.ui.receipt.viewmodel.ReceiptDetailViewModel; import java.text.DecimalFormat; +import java.util.Date; public class ReceiptDetailFragment extends Fragment { @@ -93,15 +99,15 @@ private void setFeeDetailsView(@NonNull final Receipt receipt, @NonNull final Vi DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); TextView amountView = view.findViewById(R.id.details_amount_value); - amountView.setText(view.getContext().getString(R.string.amount_view_format, + amountView.setText(view.getContext().getString(R.string.concat_string_view_format, decimalFormat.format(amount), receipt.getCurrency())); TextView fee = view.findViewById(R.id.details_fee_value); - fee.setText(view.getContext().getString(R.string.amount_view_format, + fee.setText(view.getContext().getString(R.string.concat_string_view_format, decimalFormat.format(feeAmount), receipt.getCurrency())); TextView transfer = view.findViewById(R.id.details_transfer_amount_value); - transfer.setText(view.getContext().getString(R.string.amount_view_format, + transfer.setText(view.getContext().getString(R.string.concat_string_view_format, decimalFormat.format(transferAmount), receipt.getCurrency())); } } @@ -109,11 +115,14 @@ private void setFeeDetailsView(@NonNull final Receipt receipt, @NonNull final Vi private void setDetailsView(@NonNull final Receipt receipt, @NonNull final View view) { TextView receiptId = view.findViewById(R.id.receipt_id_value); receiptId.setText(receipt.getJournalId()); - TextView date = view.findViewById(R.id.date_value); - date.setText(DateUtils.toDateFormat(DateUtils. - fromDateTimeString(receipt.getCreatedOn()), - DateFormat.is24HourFormat(view.getContext()) ? DETAIL_DATE_TIME_24H_FORMAT - : DETAIL_DATE_TIME_12H_FORMAT)); + TextView dateView = view.findViewById(R.id.date_value); + + Date date = DateUtils.fromDateTimeString(receipt.getCreatedOn()); + String timezone = DateUtils.toDateFormat(date, DETAIL_TIMEZONE); + dateView.setText(view.getContext().getString(R.string.concat_string_view_format, + formatDateTime(view.getContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_YEAR + | FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY), timezone)); if (receipt.getDetails() != null) { ReceiptDetails receiptDetails = receipt.getDetails(); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java index c2c602682..0cb31c922 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java @@ -16,6 +16,10 @@ */ package com.hyperwallet.android.ui.receipt.view; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.formatDateTime; + import static com.hyperwallet.android.model.receipt.Receipt.Entries.CREDIT; import static com.hyperwallet.android.model.receipt.Receipt.Entries.DEBIT; @@ -30,14 +34,13 @@ import com.hyperwallet.android.ui.receipt.R; import java.text.DecimalFormat; +import java.util.Date; import java.util.Locale; final class ReceiptViewUtil { static final String AMOUNT_FORMAT = "###0.00"; - static final String DETAIL_DATE_TIME_24H_FORMAT = "E MMM dd, YYYY - HH:mm zzz"; - static final String DETAIL_DATE_TIME_12H_FORMAT = "E MMM dd, YYYY - hh:mm a zzz"; - private static final String CAPTION_DATE_FORMAT = "MMMM dd, yyyy"; + static final String DETAIL_TIMEZONE = "zzz"; void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { TextView transactionTypeIcon = view.findViewById(R.id.transaction_type_icon); @@ -73,8 +76,9 @@ void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view transactionCurrency.setText(receipt.getCurrency()); transactionTitle.setText(getTransactionTitle(receipt.getType(), transactionTitle.getContext())); - transactionDate.setText(DateUtils.toDateFormat(DateUtils. - fromDateTimeString(receipt.getCreatedOn()), CAPTION_DATE_FORMAT)); + Date date = DateUtils.fromDateTimeString(receipt.getCreatedOn()); + transactionDate.setText(formatDateTime(view.getContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR)); } String getTransactionTitle(@NonNull final String receiptType, @NonNull final Context context) { diff --git a/receipt/src/main/res/values/strings.xml b/receipt/src/main/res/values/strings.xml index d6b595c3b..865db7f1a 100644 --- a/receipt/src/main/res/values/strings.xml +++ b/receipt/src/main/res/values/strings.xml @@ -15,7 +15,7 @@ Charity Name: Check Number: Website: - %s %s + %s %s Seems like, you don\'t have any Transactions, yet. From bf61a0551ae2fb579492aae8b1f85d2206da4efb Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Mon, 17 Jun 2019 09:42:05 -0700 Subject: [PATCH 12/36] update background effect to use ripple, added todos for currency formatting and exception messaging --- common/src/main/res/drawable/view_item_ripple.xml | 8 ++++++++ .../android/ui/receipt/view/ReceiptDetailActivity.java | 4 ++-- .../android/ui/receipt/view/ReceiptDetailFragment.java | 3 ++- .../android/ui/receipt/view/ReceiptViewUtil.java | 2 ++ receipt/src/main/res/layout/item_receipt.xml | 2 +- receipt/src/main/res/layout/item_receipt_with_header.xml | 2 +- 6 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 common/src/main/res/drawable/view_item_ripple.xml diff --git a/common/src/main/res/drawable/view_item_ripple.xml b/common/src/main/res/drawable/view_item_ripple.xml new file mode 100644 index 000000000..4cabe0d43 --- /dev/null +++ b/common/src/main/res/drawable/view_item_ripple.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java index 9cc136927..b382894f8 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java @@ -58,8 +58,8 @@ public void onClick(View v) { ReceiptDetailViewModel viewModel = ViewModelProviders.of(this).get(ReceiptDetailViewModel.class); viewModel.setReceipt((Receipt) parcel); } else { - throw new IllegalArgumentException("Cannot initialize " + ReceiptDetailActivity.class.getName() - + " " + EXTRA_RECEIPT + " argument is not as what is expected."); + throw new IllegalArgumentException("Argument is not an instance of " + + ReceiptDetailActivity.class.getName()); } if (savedInstanceState == null) { diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java index 9b86ccd41..fbfadcd17 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java @@ -53,7 +53,6 @@ public class ReceiptDetailFragment extends Fragment { private ReceiptDetailViewModel mReceiptDetailViewModel; public ReceiptDetailFragment() { - setRetainInstance(true); } public static ReceiptDetailFragment newInstance() { @@ -96,6 +95,8 @@ private void setFeeDetailsView(@NonNull final Receipt receipt, @NonNull final Vi double feeAmount = Double.parseDouble(receipt.getFee()); double amount = Double.parseDouble(receipt.getAmount()); double transferAmount = amount - feeAmount; + + //TODO localization of currencies in consideration DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); TextView amountView = view.findViewById(R.id.details_amount_value); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java index 0cb31c922..41def2fcf 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java @@ -48,6 +48,8 @@ void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view TextView transactionDate = view.findViewById(R.id.transaction_date); TextView transactionAmount = view.findViewById(R.id.transaction_amount); TextView transactionCurrency = view.findViewById(R.id.transaction_currency); + + //TODO localization of currencies in consideration DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); double amount = Double.parseDouble(receipt.getAmount()); String formattedAmount = decimalFormat.format(amount); diff --git a/receipt/src/main/res/layout/item_receipt.xml b/receipt/src/main/res/layout/item_receipt.xml index c30bba973..cfb204c4c 100644 --- a/receipt/src/main/res/layout/item_receipt.xml +++ b/receipt/src/main/res/layout/item_receipt.xml @@ -1,6 +1,6 @@ diff --git a/receipt/src/main/res/layout/item_receipt_with_header.xml b/receipt/src/main/res/layout/item_receipt_with_header.xml index 9e5c72649..9256f3ff8 100644 --- a/receipt/src/main/res/layout/item_receipt_with_header.xml +++ b/receipt/src/main/res/layout/item_receipt_with_header.xml @@ -22,7 +22,7 @@ From 8163d53cb1976cee4a2b6109b020a056e9baa78c Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Mon, 17 Jun 2019 12:03:52 -0700 Subject: [PATCH 13/36] ui specs changes --- .../receipt/view/ReceiptDetailFragment.java | 16 +- .../res/layout/fragment_receipt_detail.xml | 301 +++++++++--------- receipt/src/main/res/values/strings.xml | 16 +- 3 files changed, 170 insertions(+), 163 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java index fbfadcd17..0dc09fde9 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java @@ -82,11 +82,11 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat ReceiptViewUtil util = new ReceiptViewUtil(); util.setTransactionView(receipt, view); - // fee details - setFeeDetailsView(receipt, view); - // receipt details setDetailsView(receipt, view); + + // fee details + setFeeDetailsView(receipt, view); } private void setFeeDetailsView(@NonNull final Receipt receipt, @NonNull final View view) { @@ -142,15 +142,15 @@ private void setDetailsView(@NonNull final Receipt receipt, @NonNull final View view, receiptDetails.getClientPaymentId()); } - if (!TextUtils.isEmpty(receiptDetails.getNotes())) { - setViewInformation(R.id.notes_layout, R.id.notes_value, - view, receiptDetails.getNotes()); - } - if (!TextUtils.isEmpty(receiptDetails.getWebsite())) { setViewInformation(R.id.website_layout, R.id.website_value, view, receiptDetails.getWebsite()); } + + if (!TextUtils.isEmpty(receiptDetails.getNotes())) { + setViewInformation(R.id.receipt_notes_information, R.id.notes_value, + view, receiptDetails.getNotes()); + } } } diff --git a/receipt/src/main/res/layout/fragment_receipt_detail.xml b/receipt/src/main/res/layout/fragment_receipt_detail.xml index 79aafab7d..6939cc71c 100644 --- a/receipt/src/main/res/layout/fragment_receipt_detail.xml +++ b/receipt/src/main/res/layout/fragment_receipt_detail.xml @@ -12,8 +12,11 @@ android:layout_height="match_parent" app:layout_constraintTop_toBottomOf="parent"> - + + - - - - - - - - - - - - - - - - - - - - - - - @@ -174,7 +76,7 @@ android:layout_alignParentTop="true" android:layout_marginStart="@dimen/grid_margin_left" android:layout_marginTop="@dimen/grid_margin_top" - android:text="@string/receipt_id_label" + android:text="@string/journalId" android:textAppearance="@style/TextAppearance.MaterialComponents.Caption" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -204,7 +106,7 @@ android:layout_below="@+id/receipt_id_label" android:layout_marginStart="@dimen/grid_margin_left" android:layout_marginTop="@dimen/item_text_top_bottom_margin" - android:text="@string/receipt_date_label" + android:text="@string/createdOn" android:textAppearance="@style/TextAppearance.MaterialComponents.Caption" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -241,7 +143,7 @@ android:layout_alignParentTop="true" android:layout_marginStart="@dimen/grid_margin_left" android:layout_marginTop="@dimen/item_text_top_bottom_margin" - android:text="@string/client_id_label" + android:text="@string/clientPaymentId" android:textAppearance="@style/TextAppearance.MaterialComponents.Caption" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent"/> @@ -264,42 +166,6 @@ app:layout_constraintEnd_toEndOf="parent"/> - - - - - - - @@ -349,7 +215,7 @@ android:layout_alignParentTop="true" android:layout_marginStart="@dimen/grid_margin_left" android:layout_marginTop="@dimen/item_text_top_bottom_margin" - android:text="@string/check_number_label" + android:text="@string/checkNumber" android:textAppearance="@style/TextAppearance.MaterialComponents.Caption" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent"/> @@ -385,7 +251,7 @@ android:layout_alignParentTop="true" android:layout_marginStart="@dimen/grid_margin_left" android:layout_marginTop="@dimen/item_text_top_bottom_margin" - android:text="@string/website_label" + android:text="@string/website" android:textAppearance="@style/TextAppearance.MaterialComponents.Caption" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent"/> @@ -408,11 +274,152 @@ app:layout_constraintEnd_toEndOf="parent"/> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/main/res/values/strings.xml b/receipt/src/main/res/values/strings.xml index 865db7f1a..b40bd2485 100644 --- a/receipt/src/main/res/values/strings.xml +++ b/receipt/src/main/res/values/strings.xml @@ -3,18 +3,18 @@ Transactions Transaction Details Transaction - Details + Fee Specification Amount: Fee: Transfer Amount: Receipt - Receipt ID: - Date: - Client ID: - Notes: - Charity Name: - Check Number: - Website: + Receipt ID: + Date: + Client Transaction ID: + Notes + Charity Name: + Check Number: + Promo Website: %s %s Seems like, you don\'t have any Transactions, From cf23ee8b30e80a179a640019097ea97e2cc89c95 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Mon, 17 Jun 2019 13:41:27 -0700 Subject: [PATCH 14/36] update notes value layout --- receipt/src/main/res/layout/fragment_receipt_detail.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receipt/src/main/res/layout/fragment_receipt_detail.xml b/receipt/src/main/res/layout/fragment_receipt_detail.xml index 6939cc71c..a9abb5ea6 100644 --- a/receipt/src/main/res/layout/fragment_receipt_detail.xml +++ b/receipt/src/main/res/layout/fragment_receipt_detail.xml @@ -308,7 +308,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/grid_margin_left" - android:layout_marginTop="@dimen/item_text_top_bottom_margin" + android:layout_marginTop="@dimen/grid_margin_top" android:layout_marginEnd="@dimen/grid_margin_right" android:layout_marginBottom="@dimen/grid_margin_bottom" android:text="@string/text_placeholder" From 83d424dd243e140d67ce69a9eb8f03030963e456 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Mon, 17 Jun 2019 14:00:53 -0700 Subject: [PATCH 15/36] try remove lint exception --- receipt/config/lint.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/receipt/config/lint.xml b/receipt/config/lint.xml index ff446fa9e..3c83d4bb5 100644 --- a/receipt/config/lint.xml +++ b/receipt/config/lint.xml @@ -4,7 +4,4 @@ - - - \ No newline at end of file From 972dd0cb4f1997e5b64ff4aed92df61bcf2083c3 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Mon, 17 Jun 2019 14:49:14 -0700 Subject: [PATCH 16/36] fixed lint --- receipt/config/lint.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/receipt/config/lint.xml b/receipt/config/lint.xml index 3c83d4bb5..ff446fa9e 100644 --- a/receipt/config/lint.xml +++ b/receipt/config/lint.xml @@ -4,4 +4,7 @@ + + + \ No newline at end of file From 7ddf49d5b7b005cd1c912bbf6a5e02728762f925 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Tue, 18 Jun 2019 08:09:45 -0700 Subject: [PATCH 17/36] by design decision removing binding classes into duplicate code --- .../ui/receipt/view/ListReceiptFragment.java | 61 +++++++++++- .../receipt/view/ReceiptDetailFragment.java | 65 ++++++++++++- .../ui/receipt/view/ReceiptViewUtil.java | 96 ------------------- 3 files changed, 119 insertions(+), 103 deletions(-) delete mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index 1dce9c4ca..e1fd220a2 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -21,6 +21,10 @@ import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; import static android.text.format.DateUtils.formatDateTime; +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; @@ -44,8 +48,10 @@ import com.hyperwallet.android.ui.receipt.R; import com.hyperwallet.android.ui.receipt.viewmodel.ListReceiptViewModel; +import java.text.DecimalFormat; import java.util.Calendar; import java.util.Date; +import java.util.Locale; import java.util.Objects; public class ListReceiptFragment extends Fragment { @@ -137,7 +143,7 @@ public boolean areContentsTheSame(@NonNull final Receipt oldItem, @NonNull final private static class ListReceiptAdapter extends PagedListAdapter { - private static final String HEADER_DATE_FORMAT = "MMMM yyyy"; + static final String AMOUNT_FORMAT = "###0.00"; private static final int HEADER_VIEW_TYPE = 1; private static final int DATA_VIEW_TYPE = 0; private final ListReceiptViewModel mReceiptViewModel; @@ -204,14 +210,63 @@ class ReceiptViewHolder extends RecyclerView.ViewHolder { } void bind(@NonNull final Receipt receipt) { - ReceiptViewUtil util = new ReceiptViewUtil(); - util.setTransactionView(receipt, itemView); mView.setOnClickListener(new OneClickListener() { @Override public void onOneClick(View v) { mListReceiptViewModel.setDetailNavigation(receipt); } }); + + // By design decision from here under, this code is also repeated in ReceiptDetailFragment + TextView transactionTypeIcon = itemView.findViewById(R.id.transaction_type_icon); + TextView transactionTitle = itemView.findViewById(R.id.transaction_title); + TextView transactionDate = itemView.findViewById(R.id.transaction_date); + TextView transactionAmount = itemView.findViewById(R.id.transaction_amount); + TextView transactionCurrency = itemView.findViewById(R.id.transaction_currency); + + //TODO localization of currencies in consideration + DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); + double amount = Double.parseDouble(receipt.getAmount()); + String formattedAmount = decimalFormat.format(amount); + + if (CREDIT.equals(receipt.getEntry())) { + transactionAmount.setTextColor(transactionAmount.getContext() + .getResources().getColor(R.color.positiveColor)); + transactionAmount.setText(transactionAmount.getContext() + .getString(R.string.credit_sign, formattedAmount)); + transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() + .getResources().getColor(R.color.positiveColor)); + transactionTypeIcon.setBackground(transactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_positive)); + transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.credit)); + } else if (DEBIT.equals(receipt.getEntry())) { + transactionAmount.setTextColor(transactionAmount.getContext() + .getResources().getColor(R.color.colorAccent)); + transactionAmount.setText(transactionAmount.getContext() + .getString(R.string.debit_sign, formattedAmount)); + transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() + .getResources().getColor(R.color.colorAccent)); + transactionTypeIcon.setBackground(transactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_negative)); + transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.debit)); + } + + transactionCurrency.setText(receipt.getCurrency()); + transactionTitle.setText(getTransactionTitle(receipt.getType(), transactionTitle.getContext())); + Date date = DateUtils.fromDateTimeString(receipt.getCreatedOn()); + transactionDate.setText(formatDateTime(itemView.getContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR)); + } + + 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; } } diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java index 0dc09fde9..ae2490c09 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java @@ -23,9 +23,10 @@ import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; import static android.text.format.DateUtils.formatDateTime; -import static com.hyperwallet.android.ui.receipt.view.ReceiptViewUtil.AMOUNT_FORMAT; -import static com.hyperwallet.android.ui.receipt.view.ReceiptViewUtil.DETAIL_TIMEZONE; +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.text.TextUtils; import android.view.LayoutInflater; @@ -47,9 +48,13 @@ import java.text.DecimalFormat; import java.util.Date; +import java.util.Locale; public class ReceiptDetailFragment extends Fragment { + static final String AMOUNT_FORMAT = "###0.00"; + static final String DETAIL_TIMEZONE = "zzz"; + private ReceiptDetailViewModel mReceiptDetailViewModel; public ReceiptDetailFragment() { @@ -79,8 +84,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat Receipt receipt = mReceiptDetailViewModel.getReceipt(); // transactions - ReceiptViewUtil util = new ReceiptViewUtil(); - util.setTransactionView(receipt, view); + setTransactionView(receipt, view); // receipt details setDetailsView(receipt, view); @@ -89,6 +93,59 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat setFeeDetailsView(receipt, view); } + // By design decision, this code is also repeated in ListReceiptFragment + private void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { + TextView transactionTypeIcon = view.findViewById(R.id.transaction_type_icon); + TextView transactionTitle = view.findViewById(R.id.transaction_title); + TextView transactionDate = view.findViewById(R.id.transaction_date); + TextView transactionAmount = view.findViewById(R.id.transaction_amount); + TextView transactionCurrency = view.findViewById(R.id.transaction_currency); + + //TODO localization of currencies in consideration + DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); + double amount = Double.parseDouble(receipt.getAmount()); + String formattedAmount = decimalFormat.format(amount); + + if (CREDIT.equals(receipt.getEntry())) { + transactionAmount.setTextColor(transactionAmount.getContext() + .getResources().getColor(R.color.positiveColor)); + transactionAmount.setText(transactionAmount.getContext() + .getString(R.string.credit_sign, formattedAmount)); + transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() + .getResources().getColor(R.color.positiveColor)); + transactionTypeIcon.setBackground(transactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_positive)); + transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.credit)); + } else if (DEBIT.equals(receipt.getEntry())) { + transactionAmount.setTextColor(transactionAmount.getContext() + .getResources().getColor(R.color.colorAccent)); + transactionAmount.setText(transactionAmount.getContext() + .getString(R.string.debit_sign, formattedAmount)); + transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() + .getResources().getColor(R.color.colorAccent)); + transactionTypeIcon.setBackground(transactionTypeIcon.getContext() + .getDrawable(R.drawable.circle_negative)); + transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.debit)); + } + + transactionCurrency.setText(receipt.getCurrency()); + transactionTitle.setText(getTransactionTitle(receipt.getType(), transactionTitle.getContext())); + Date date = DateUtils.fromDateTimeString(receipt.getCreatedOn()); + transactionDate.setText(formatDateTime(view.getContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR)); + } + + private 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; + } + private void setFeeDetailsView(@NonNull final Receipt receipt, @NonNull final View view) { if (!TextUtils.isEmpty(receipt.getFee())) { view.findViewById(R.id.fee_details_layout).setVisibility(View.VISIBLE); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java deleted file mode 100644 index 41def2fcf..000000000 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptViewUtil.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.ui.receipt.view; - -import static android.text.format.DateUtils.FORMAT_SHOW_DATE; -import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; -import static android.text.format.DateUtils.formatDateTime; - -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.view.View; -import android.widget.TextView; - -import androidx.annotation.NonNull; - -import com.hyperwallet.android.model.receipt.Receipt; -import com.hyperwallet.android.ui.common.util.DateUtils; -import com.hyperwallet.android.ui.receipt.R; - -import java.text.DecimalFormat; -import java.util.Date; -import java.util.Locale; - -final class ReceiptViewUtil { - - static final String AMOUNT_FORMAT = "###0.00"; - static final String DETAIL_TIMEZONE = "zzz"; - - void setTransactionView(@NonNull final Receipt receipt, @NonNull final View view) { - TextView transactionTypeIcon = view.findViewById(R.id.transaction_type_icon); - TextView transactionTitle = view.findViewById(R.id.transaction_title); - TextView transactionDate = view.findViewById(R.id.transaction_date); - TextView transactionAmount = view.findViewById(R.id.transaction_amount); - TextView transactionCurrency = view.findViewById(R.id.transaction_currency); - - //TODO localization of currencies in consideration - DecimalFormat decimalFormat = new DecimalFormat(AMOUNT_FORMAT); - double amount = Double.parseDouble(receipt.getAmount()); - String formattedAmount = decimalFormat.format(amount); - - if (CREDIT.equals(receipt.getEntry())) { - transactionAmount.setTextColor(transactionAmount.getContext() - .getResources().getColor(R.color.positiveColor)); - transactionAmount.setText(transactionAmount.getContext() - .getString(R.string.credit_sign, formattedAmount)); - transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() - .getResources().getColor(R.color.positiveColor)); - transactionTypeIcon.setBackground(transactionTypeIcon.getContext() - .getDrawable(R.drawable.circle_positive)); - transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.credit)); - } else if (DEBIT.equals(receipt.getEntry())) { - transactionAmount.setTextColor(transactionAmount.getContext() - .getResources().getColor(R.color.colorAccent)); - transactionAmount.setText(transactionAmount.getContext() - .getString(R.string.debit_sign, formattedAmount)); - transactionTypeIcon.setTextColor(transactionTypeIcon.getContext() - .getResources().getColor(R.color.colorAccent)); - transactionTypeIcon.setBackground(transactionTypeIcon.getContext() - .getDrawable(R.drawable.circle_negative)); - transactionTypeIcon.setText(transactionTypeIcon.getContext().getText(R.string.debit)); - } - - transactionCurrency.setText(receipt.getCurrency()); - transactionTitle.setText(getTransactionTitle(receipt.getType(), transactionTitle.getContext())); - Date date = DateUtils.fromDateTimeString(receipt.getCreatedOn()); - transactionDate.setText(formatDateTime(view.getContext(), date.getTime(), - FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR)); - } - - 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; - } -} From 2be481ea428f42211b108b32ac07d06f17ae0824 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Tue, 18 Jun 2019 11:06:30 -0700 Subject: [PATCH 18/36] synced with core sdk --- .../receipt/repository/ReceiptDataSource.java | 4 +-- .../repository/ReceiptDataSourceTest.java | 32 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java index f6e30479b..0b6a7a1e4 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java @@ -71,7 +71,7 @@ public void loadInitial(@NonNull final LoadInitialParams params, .limit(params.requestedLoadSize) .sortByCreatedOnDesc().build(); - getHyperwallet().listReceipts(queryParam, + getHyperwallet().listUserReceipts(queryParam, new HyperwalletListener>() { @Override public void onSuccess(@Nullable HyperwalletPageList result) { @@ -129,7 +129,7 @@ public void loadAfter(@NonNull LoadParams params, .offset(params.key) .sortByCreatedOnDesc().build(); - getHyperwallet().listReceipts(queryParam, + getHyperwallet().listUserReceipts(queryParam, new HyperwalletListener>() { @Override public void onSuccess(@Nullable HyperwalletPageList result) { diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java index 9cf699e83..50aa0ad5e 100644 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java @@ -96,13 +96,13 @@ public Object answer(InvocationOnMock invocation) { listener.onSuccess(response); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mInitialCallback).onResult(mListArgumentCaptor.capture(), mPreviousCaptor.capture(), mNextCaptor.capture()); @@ -149,13 +149,13 @@ public Object answer(InvocationOnMock invocation) { listener.onSuccess(null); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt(), anyInt()); @@ -177,13 +177,13 @@ public Object answer(InvocationOnMock invocation) { listener.onFailure(new HyperwalletException(errors)); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt(), anyInt()); @@ -211,13 +211,13 @@ public Object answer(InvocationOnMock invocation) { listener.onFailure(new HyperwalletException(errors)); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt(), anyInt()); @@ -248,13 +248,13 @@ public Object answer(InvocationOnMock invocation) { listener.onSuccess(response); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mLoadAfterCallback).onResult(mListArgumentCaptor.capture(), mNextCaptor.capture()); @@ -299,13 +299,13 @@ public Object answer(InvocationOnMock invocation) { listener.onSuccess(null); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.>any(), anyInt()); @@ -327,13 +327,13 @@ public Object answer(InvocationOnMock invocation) { listener.onFailure(new HyperwalletException(errors)); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt()); @@ -362,13 +362,13 @@ public Object answer(InvocationOnMock invocation) { listener.onFailure(new HyperwalletException(errors)); return listener; } - }).when(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + }).when(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); // test mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); - verify(mHyperwallet).listReceipts(any(ReceiptQueryParam.class), + verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.anyList(), anyInt()); From 7443ad6a5b4c11d1df70666dee478cbcc7db8e6e Mon Sep 17 00:00:00 2001 From: Flavio Mattos Date: Tue, 18 Jun 2019 12:34:14 -0700 Subject: [PATCH 19/36] fixing typo --- .../android/ui/receipt/view/ListReceiptFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index e1fd220a2..69605557c 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -159,14 +159,14 @@ public int getItemViewType(final int position) { if (position != 0) { Receipt previous = getItem(position - 1); Receipt current = getItem(position); - if (isDataViewType(previous, current)) { + if (isDateViewType(previous, current)) { return DATA_VIEW_TYPE; } } return HEADER_VIEW_TYPE; } - boolean isDataViewType(@NonNull final Receipt previous, @NonNull final Receipt current) { + boolean isDateViewType(@NonNull final Receipt previous, @NonNull final Receipt current) { Calendar prev = Calendar.getInstance(); prev.setTime(DateUtils.fromDateTimeString(previous.getCreatedOn())); Calendar curr = Calendar.getInstance(); From ff14349729d3c9c408a3ae29f3e133f216e191d0 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Tue, 18 Jun 2019 13:09:46 -0700 Subject: [PATCH 20/36] revert rename --- .../android/ui/receipt/view/ListReceiptFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index 69605557c..e1fd220a2 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -159,14 +159,14 @@ public int getItemViewType(final int position) { if (position != 0) { Receipt previous = getItem(position - 1); Receipt current = getItem(position); - if (isDateViewType(previous, current)) { + if (isDataViewType(previous, current)) { return DATA_VIEW_TYPE; } } return HEADER_VIEW_TYPE; } - boolean isDateViewType(@NonNull final Receipt previous, @NonNull final Receipt current) { + boolean isDataViewType(@NonNull final Receipt previous, @NonNull final Receipt current) { Calendar prev = Calendar.getInstance(); prev.setTime(DateUtils.fromDateTimeString(previous.getCreatedOn())); Calendar curr = Calendar.getInstance(); From 43b351f24ebf241796e24c44f0647c7ad03dfa08 Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Tue, 18 Jun 2019 13:39:10 -0700 Subject: [PATCH 21/36] Automation for receipt details and receipt network retry (#43) --- .../android/ui/receipt/ListReceiptsTest.java | 210 ++++++++++++++++-- .../receipt/repository/ReceiptDataSource.java | 7 + .../test/resources/receipt_list_response.json | 8 +- 3 files changed, 208 insertions(+), 17 deletions(-) diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java index 436472ea9..3e939699b 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java @@ -1,9 +1,19 @@ package com.hyperwallet.android.ui.receipt; +import static android.text.format.DateUtils.FORMAT_ABBREV_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_TIME; +import static android.text.format.DateUtils.FORMAT_SHOW_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.formatDateTime; + import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; 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.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withText; @@ -22,11 +32,15 @@ import android.widget.TextView; import androidx.test.core.app.ApplicationProvider; +import androidx.test.espresso.IdlingRegistry; import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.ui.common.util.DateUtils; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; import com.hyperwallet.android.ui.receipt.repository.ReceiptRepositoryFactory; import com.hyperwallet.android.ui.receipt.rule.HyperwalletExternalResourceManager; import com.hyperwallet.android.ui.receipt.rule.HyperwalletMockWebServer; @@ -41,7 +55,11 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Date; import java.util.Locale; +import java.util.concurrent.TimeUnit; + +import okhttp3.mockwebserver.MockResponse; @RunWith(AndroidJUnit4.class) public class ListReceiptsTest { @@ -69,8 +87,18 @@ public void cleanup() { ReceiptRepositoryFactory.clearInstance(); } + @Before + public void registerIdlingResource() { + IdlingRegistry.getInstance().register(EspressoIdlingResource.getIdlingResource()); + } + + @After + public void unregisterIdlingResource() { + IdlingRegistry.getInstance().unregister(EspressoIdlingResource.getIdlingResource()); + } + @Test - public void testListReceipts_userHasMultipleTransactions() { + public void testListReceipt_userHasMultipleTransactions() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_list_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); @@ -92,7 +120,7 @@ public void testListReceipts_userHasMultipleTransactions() { 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"))))); + matches(atPosition(0, hasDescendant(withText("June 7, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, @@ -102,7 +130,7 @@ public void testListReceipts_userHasMultipleTransactions() { 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"))))); + matches(atPosition(1, hasDescendant(withText("June 2, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("CAD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, @@ -112,7 +140,7 @@ public void testListReceipts_userHasMultipleTransactions() { 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"))))); + matches(atPosition(2, hasDescendant(withText("June 1, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)) @@ -124,14 +152,14 @@ public void testListReceipts_userHasMultipleTransactions() { 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"))))); + matches(atPosition(3, hasDescendant(withText("December 1, 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() { + public void testListReceipt_userHasCreditTransaction() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_credit_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); @@ -153,14 +181,14 @@ public void testListReceipts_displayCreditTransaction() { 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"))))); + matches(atPosition(0, hasDescendant(withText("June 2, 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() { + public void testListReceipt_userHasDebitTransaction() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_debit_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); @@ -182,14 +210,14 @@ public void testListReceipts_displayDebitTransaction() { 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"))))); + matches(atPosition(0, hasDescendant(withText("May 2, 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() { + public void testListReceipt_userHasUnknownTransactionType() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_unknown_type_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); @@ -211,7 +239,7 @@ public void testListReceipts_displayUnknownTransactionType() { 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"))))); + matches(atPosition(0, hasDescendant(withText("June 2, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("CAD"))))); onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); @@ -231,7 +259,120 @@ public void testListReceipt_userHasNoTransactions() { } @Test - public void testListReceipt_displayPagedTransactions() throws InterruptedException { + public void testListReceipt_clickTransactionDisplaysDetails() { + 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)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); + + onView(withId(R.id.transaction_header_text)).check(matches(withText(R.string.transaction_header_text))); + onView(withId(R.id.transaction_type_icon)).check(matches(withText(R.string.credit))); + onView(withId(R.id.transaction_title)).check(matches(withText(R.string.payment))); + onView(withId(R.id.transaction_amount)).check(matches(withText("+ 20.00"))); + onView(withId(R.id.transaction_currency)).check(matches(withText("USD"))); + onView(withId(R.id.transaction_date)).check(matches(withText("June 7, 2019"))); + + onView(withId(R.id.receipt_details_header_label)).check(matches(withText(R.string.receipt_header_label))); + onView(withId(R.id.receipt_id_label)).check(matches(withText(R.string.journalId))); + onView(withId(R.id.receipt_id_value)).check(matches(withText("3051579"))); + onView(withId(R.id.date_label)).check(matches(withText(R.string.createdOn))); + + Date date = DateUtils.fromDateTimeString("2019-06-07T17:08:58"); + String timezone = DateUtils.toDateFormat(date, "zzz"); + String text = mActivityTestRule.getActivity().getApplicationContext().getString( + R.string.concat_string_view_format, + formatDateTime(mActivityTestRule.getActivity().getApplicationContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_YEAR + | FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY), timezone); + onView(withId(R.id.date_value)).check(matches(withText(text))); + + onView(withId(R.id.client_id_label)).check(matches(withText(R.string.clientPaymentId))); + onView(withId(R.id.client_id_value)).check(matches(withText("8OxXefx5"))); + onView(withId(R.id.charity_label)).check(matches(withText(R.string.charityName))); + onView(withId(R.id.charity_value)).check(matches(withText("Sample Charity"))); + onView(withId(R.id.check_number_label)).check(matches(withText(R.string.checkNumber))); + onView(withId(R.id.check_number_value)).check(matches(withText("Sample Check Number"))); + onView(withId(R.id.website_label)).check(matches(withText(R.string.website))); + onView(withId(R.id.website_value)).check(matches(withText("https://api.sandbox.hyperwallet.com"))); + onView(withText("A Person")).check(doesNotExist()); + + onView(withId(R.id.receipt_notes_header_label)).check(matches(withText(R.string.notes))); + onView(withId(R.id.notes_value)).check( + matches(withText("Sample payment for the period of June 15th, 2019 to July 23, 2019"))); + + onView(withId(R.id.details_header_text)).check(matches(withText(R.string.fee_details_header_text))); + onView(withId(R.id.details_amount_label)).check(matches(withText(R.string.details_amount_label))); + onView(withId(R.id.details_amount_value)).check(matches(withText("20.00 USD"))); + onView(withId(R.id.details_fee_label)).check(matches(withText(R.string.fee_label))); + onView(withId(R.id.details_fee_value)).check(matches(withText("2.25 USD"))); + onView(withId(R.id.details_transfer_amount_label)).check(matches(withText(R.string.transfer_amount_label))); + onView(withId(R.id.details_transfer_amount_value)).check(matches(withText("17.75 USD"))); + } + + @Test + public void testListReceipt_clickTransactionDisplaysDetailsWithoutFees() { + 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)).perform(RecyclerViewActions.actionOnItemAtPosition(3, click())); + + onView(withId(R.id.transaction_header_text)).check(matches(withText(R.string.transaction_header_text))); + onView(withId(R.id.transaction_type_icon)).check(matches(withText(R.string.debit))); + onView(withId(R.id.transaction_title)).check(matches(withText(R.string.transfer_to_prepaid_card))); + onView(withId(R.id.transaction_amount)).check(matches(withText("- 18.05"))); + onView(withId(R.id.transaction_currency)).check(matches(withText("USD"))); + onView(withId(R.id.transaction_date)).check(matches(withText("December 1, 2018"))); + + onView(withId(R.id.receipt_details_header_label)).check(matches(withText(R.string.receipt_header_label))); + onView(withId(R.id.receipt_id_label)).check(matches(withText(R.string.journalId))); + onView(withId(R.id.receipt_id_value)).check(matches(withText("3051590"))); + onView(withId(R.id.date_label)).check(matches(withText(R.string.createdOn))); + + Date date = DateUtils.fromDateTimeString("2018-12-01T17:12:18"); + String timezone = DateUtils.toDateFormat(date, "zzz"); + String text = mActivityTestRule.getActivity().getApplicationContext().getString( + R.string.concat_string_view_format, + formatDateTime(mActivityTestRule.getActivity().getApplicationContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_YEAR + | FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY), timezone); + onView(withId(R.id.date_value)).check(matches(withText(text))); + + onView(withId(R.id.client_id_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.client_id_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.charity_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.charity_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.check_number_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.check_number_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.website_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.website_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + + onView(withId(R.id.receipt_notes_information)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.receipt_notes_header_label)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.notes_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + } + + @Test + public void testListReceipt_verifyTransactionsLoadedUponScrolling() throws InterruptedException { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_list_paged_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager @@ -265,7 +406,7 @@ public void testListReceipt_displayPagedTransactions() throws InterruptedExcepti } @Test - public void testListReceipts_checkDateTextOnLocaleChange() { + public void testListReceipt_checkDateTextOnLocaleChange() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_debit_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); @@ -276,8 +417,47 @@ public void testListReceipts_checkDateTextOnLocaleChange() { // 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(); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("2 maggio 2019"))))); + } + + @Test + public void testListReceipt_displaysNetworkErrorDialogOnConnectionTimeout() { + mMockWebServer.getServer().enqueue(new MockResponse().setResponseCode(HTTP_OK).setBody(sResourceManager + .getResourceContent("receipt_debit_response.json")).throttleBody(1, 5, TimeUnit.SECONDS)); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_debit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + mActivityTestRule.launchActivity(null); + + // assert error dialog information exist in portrait mode + onView(withText(R.string.error_dialog_connectivity_title)).check(matches(isDisplayed())); + onView(withText(R.string.io_exception)).check(matches(isDisplayed())); + onView(withId(android.R.id.button1)).check(matches(withText(R.string.try_again_button_label))); + onView(withId(android.R.id.button2)).check(matches(withText(R.string.cancel_button_label))); + + // retry button clicked + onView(withId(android.R.id.button1)).perform(click()); + onView(withText(R.string.error_dialog_connectivity_title)).check(doesNotExist()); + + // 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.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( + matches(atPosition(0, hasDescendant(withText("- 18.05"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("May 2, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); } private void setLocale(Locale locale) { diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java index 0b6a7a1e4..fd0c3b654 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java @@ -31,6 +31,7 @@ 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.util.EspressoIdlingResource; import com.hyperwallet.android.ui.common.viewmodel.Event; import java.util.Calendar; @@ -71,6 +72,7 @@ public void loadInitial(@NonNull final LoadInitialParams params, .limit(params.requestedLoadSize) .sortByCreatedOnDesc().build(); + EspressoIdlingResource.increment(); getHyperwallet().listUserReceipts(queryParam, new HyperwalletListener>() { @Override @@ -86,12 +88,14 @@ public void onSuccess(@Nullable HyperwalletPageList result) { // reset mLoadInitialCallback = null; mLoadInitialParams = null; + EspressoIdlingResource.decrement(); } @Override public void onFailure(HyperwalletException exception) { mIsFetchingData.postValue(Boolean.FALSE); mErrors.postValue(new Event<>(exception.getHyperwalletErrors())); + EspressoIdlingResource.decrement(); } @Override @@ -129,6 +133,7 @@ public void loadAfter(@NonNull LoadParams params, .offset(params.key) .sortByCreatedOnDesc().build(); + EspressoIdlingResource.increment(); getHyperwallet().listUserReceipts(queryParam, new HyperwalletListener>() { @Override @@ -144,12 +149,14 @@ public void onSuccess(@Nullable HyperwalletPageList result) { // reset mLoadAfterCallback = null; mLoadAfterParams = null; + EspressoIdlingResource.decrement(); } @Override public void onFailure(HyperwalletException exception) { mIsFetchingData.postValue(Boolean.FALSE); mErrors.postValue(new Event<>(exception.getHyperwalletErrors())); + EspressoIdlingResource.decrement(); } @Override diff --git a/receipt/src/test/resources/receipt_list_response.json b/receipt/src/test/resources/receipt_list_response.json index 7e7cc58af..4ec2de4fe 100644 --- a/receipt/src/test/resources/receipt_list_response.json +++ b/receipt/src/test/resources/receipt_list_response.json @@ -11,11 +11,15 @@ "sourceToken": "act-12345", "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", "amount": "20.00", - "fee": "0.00", + "fee": "2.25", "currency": "USD", "details": { "clientPaymentId": "8OxXefx5", - "payeeName": "A Person" + "payeeName": "A Person", + "website": "https://api.sandbox.hyperwallet.com", + "notes": "Sample payment for the period of June 15th, 2019 to July 23, 2019", + "charityName": "Sample Charity", + "checkNumber": "Sample Check Number" } }, { From 9a87a91c19a3c427756a604d0e28912b7088f3f0 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Tue, 18 Jun 2019 14:24:52 -0700 Subject: [PATCH 22/36] added finalizer identifiers --- .../android/ui/receipt/view/ReceiptDetailActivity.java | 3 ++- .../android/ui/receipt/view/ReceiptDetailFragment.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java index b382894f8..9dd1a85fa 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailActivity.java @@ -21,6 +21,7 @@ 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; @@ -37,7 +38,7 @@ public class ReceiptDetailActivity extends AppCompatActivity { public static final String EXTRA_RECEIPT = "RECEIPT"; @Override - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_receipt_detail); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java index ae2490c09..8e8f99dec 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java @@ -66,19 +66,19 @@ public static ReceiptDetailFragment newInstance() { } @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReceiptDetailViewModel = ViewModelProviders.of(requireActivity()).get(ReceiptDetailViewModel.class); } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, + @Nullable final Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_receipt_detail, container, false); } @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); Receipt receipt = mReceiptDetailViewModel.getReceipt(); From ca29ad47b33229993c3bbf1c9364cd5689e57d13 Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Tue, 18 Jun 2019 16:05:18 -0700 Subject: [PATCH 23/36] Updating response throttling --- .../com/hyperwallet/android/ui/receipt/ListReceiptsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java index 3e939699b..ee3bb4f03 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java @@ -423,7 +423,7 @@ public void testListReceipt_checkDateTextOnLocaleChange() { @Test public void testListReceipt_displaysNetworkErrorDialogOnConnectionTimeout() { mMockWebServer.getServer().enqueue(new MockResponse().setResponseCode(HTTP_OK).setBody(sResourceManager - .getResourceContent("receipt_debit_response.json")).throttleBody(1, 5, TimeUnit.SECONDS)); + .getResourceContent("receipt_debit_response.json")).throttleBody(512, 15, TimeUnit.SECONDS)); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_debit_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); From 2ac6d59265dc88e34c76a6b682c9c8146dfe95e9 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 19 Jun 2019 07:23:15 -0700 Subject: [PATCH 24/36] renamed receipts to user list specific --- ...ptsTest.java => ListUserReceiptsTest.java} | 12 +-- receipt/src/main/AndroidManifest.xml | 2 +- ...Source.java => UserReceiptDataSource.java} | 6 +- ...java => UserReceiptDataSourceFactory.java} | 16 ++-- ...sitory.java => UserReceiptRepository.java} | 2 +- ...java => UserReceiptRepositoryFactory.java} | 22 +++--- ...pl.java => UserReceiptRepositoryImpl.java} | 22 +++--- .../ui/receipt/view/ListReceiptFragment.java | 30 ++++---- ...vity.java => ListUserReceiptActivity.java} | 24 +++--- ...del.java => ListUserReceiptViewModel.java} | 37 +++++----- ...ipt.xml => activity_list_user_receipt.xml} | 6 +- .../ReceiptRepositoryFactoryTest.java | 39 ---------- ... => UserReceiptDataSourceFactoryTest.java} | 10 +-- ...st.java => UserReceiptDataSourceTest.java} | 74 +++++++++---------- .../UserReceiptRepositoryFactoryTest.java | 39 ++++++++++ .../hyperwallet/android/ui/HyperwalletUi.java | 8 +- 16 files changed, 174 insertions(+), 175 deletions(-) rename receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/{ListReceiptsTest.java => ListUserReceiptsTest.java} (98%) rename receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/{ReceiptDataSource.java => UserReceiptDataSource.java} (97%) rename receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/{ReceiptDataSourceFactory.java => UserReceiptDataSourceFactory.java} (76%) rename receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/{ReceiptRepository.java => UserReceiptRepository.java} (98%) rename receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/{ReceiptRepositoryFactory.java => UserReceiptRepositoryFactory.java} (70%) rename receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/{ReceiptRepositoryImpl.java => UserReceiptRepositoryImpl.java} (81%) rename receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/{ListReceiptActivity.java => ListUserReceiptActivity.java} (84%) rename receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/{ListReceiptViewModel.java => ListUserReceiptViewModel.java} (69%) rename receipt/src/main/res/layout/{activity_list_receipt.xml => activity_list_user_receipt.xml} (91%) delete mode 100644 receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactoryTest.java rename receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/{ReceiptDataSourceFactoryTest.java => UserReceiptDataSourceFactoryTest.java} (72%) rename receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/{ReceiptDataSourceTest.java => UserReceiptDataSourceTest.java} (85%) create mode 100644 receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java similarity index 98% rename from receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java rename to receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java index ee3bb4f03..3502cf704 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java @@ -41,12 +41,12 @@ import com.hyperwallet.android.Hyperwallet; import com.hyperwallet.android.ui.common.util.DateUtils; import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; -import com.hyperwallet.android.ui.receipt.repository.ReceiptRepositoryFactory; +import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepositoryFactory; import com.hyperwallet.android.ui.receipt.rule.HyperwalletExternalResourceManager; import com.hyperwallet.android.ui.receipt.rule.HyperwalletMockWebServer; import com.hyperwallet.android.ui.receipt.util.RecyclerViewCountAssertion; import com.hyperwallet.android.ui.receipt.util.TestAuthenticationProvider; -import com.hyperwallet.android.ui.receipt.view.ListReceiptActivity; +import com.hyperwallet.android.ui.receipt.view.ListUserReceiptActivity; import org.junit.After; import org.junit.Before; @@ -62,15 +62,15 @@ import okhttp3.mockwebserver.MockResponse; @RunWith(AndroidJUnit4.class) -public class ListReceiptsTest { +public class ListUserReceiptsTest { @ClassRule public static HyperwalletExternalResourceManager sResourceManager = new HyperwalletExternalResourceManager(); @Rule public HyperwalletMockWebServer mMockWebServer = new HyperwalletMockWebServer(8080); @Rule - public ActivityTestRule mActivityTestRule = - new ActivityTestRule<>(ListReceiptActivity.class, true, false); + public ActivityTestRule mActivityTestRule = + new ActivityTestRule<>(ListUserReceiptActivity.class, true, false); @Before public void setup() { @@ -84,7 +84,7 @@ public void setup() { @After public void cleanup() { - ReceiptRepositoryFactory.clearInstance(); + UserReceiptRepositoryFactory.clearInstance(); } @Before diff --git a/receipt/src/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index fbfa141a9..3cf88bfc1 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ android:theme="@style/AppTheme.NoActionBar"/> diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java similarity index 97% rename from receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java index fd0c3b654..d281e656e 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java @@ -37,10 +37,10 @@ import java.util.Calendar; /** - * ReceiptDataSource mediates communication to HW API Platform particularly on + * UserReceiptDataSource mediates communication to HW API Platform particularly on * Receipts V3 API */ -public class ReceiptDataSource extends PageKeyedDataSource { +public class UserReceiptDataSource extends PageKeyedDataSource { private static final int YEAR_BEFORE_NOW = -1; private final Calendar mCalendarYearBeforeNow; @@ -51,7 +51,7 @@ public class ReceiptDataSource extends PageKeyedDataSource { private LoadCallback mLoadAfterCallback; private LoadParams mLoadAfterParams; - ReceiptDataSource() { + UserReceiptDataSource() { super(); mCalendarYearBeforeNow = Calendar.getInstance(); mCalendarYearBeforeNow.add(Calendar.YEAR, YEAR_BEFORE_NOW); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java similarity index 76% rename from receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactory.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java index ca3186540..5d552f557 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java @@ -24,22 +24,22 @@ /** * Data source factory that uses {@link DataSource.Factory} facility */ -public class ReceiptDataSourceFactory extends DataSource.Factory { +public class UserReceiptDataSourceFactory extends DataSource.Factory { - private final MutableLiveData mDataSourceMutableLiveData; - private final ReceiptDataSource mReceiptDataSource; + private final MutableLiveData mDataSourceMutableLiveData; + private final UserReceiptDataSource mUserReceiptDataSource; - ReceiptDataSourceFactory() { + UserReceiptDataSourceFactory() { super(); - mReceiptDataSource = new ReceiptDataSource(); + mUserReceiptDataSource = new UserReceiptDataSource(); mDataSourceMutableLiveData = new MutableLiveData<>(); - mDataSourceMutableLiveData.setValue(mReceiptDataSource); + mDataSourceMutableLiveData.setValue(mUserReceiptDataSource); } /** * Returns observable members of receipt data source */ - LiveData getReceiptDataSource() { + LiveData getUserReceiptDataSource() { return mDataSourceMutableLiveData; } @@ -49,6 +49,6 @@ LiveData getReceiptDataSource() { @NonNull @Override public DataSource create() { - return mReceiptDataSource; + return mUserReceiptDataSource; } } diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepository.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepository.java similarity index 98% rename from receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepository.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepository.java index 2db846a4f..efafa90a2 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepository.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepository.java @@ -26,7 +26,7 @@ /** * Receipt Repository Contract */ -public interface ReceiptRepository { +public interface UserReceiptRepository { /** * Load receipts information, consumer can subscribe to receipts data changes events diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactory.java similarity index 70% rename from receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactory.java index 8fc76d7ab..8afc69437 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactory.java @@ -17,15 +17,15 @@ package com.hyperwallet.android.ui.receipt.repository; /** - * {@link ReceiptRepository} factory + * {@link UserReceiptRepository} factory */ -public class ReceiptRepositoryFactory { +public class UserReceiptRepositoryFactory { - private static ReceiptRepositoryFactory sInstance; - private final ReceiptRepository mReceiptRepository; + private static UserReceiptRepositoryFactory sInstance; + private final UserReceiptRepository mUserReceiptRepository; - private ReceiptRepositoryFactory() { - mReceiptRepository = new ReceiptRepositoryImpl(); + private UserReceiptRepositoryFactory() { + mUserReceiptRepository = new UserReceiptRepositoryImpl(); } /** @@ -33,9 +33,9 @@ private ReceiptRepositoryFactory() { * * @return receipt repository factory instance */ - public static synchronized ReceiptRepositoryFactory getInstance() { + public static synchronized UserReceiptRepositoryFactory getInstance() { if (sInstance == null) { - sInstance = new ReceiptRepositoryFactory(); + sInstance = new UserReceiptRepositoryFactory(); } return sInstance; } @@ -48,9 +48,9 @@ public static void clearInstance() { } /** - * @return ReceiptRepository instance implementation + * @return UserReceiptRepository instance implementation * */ - public ReceiptRepository getReceiptRepository() { - return mReceiptRepository; + public UserReceiptRepository getUserReceiptRepository() { + return mUserReceiptRepository; } } diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java similarity index 81% rename from receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryImpl.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java index 74fe8755d..864d13b2e 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryImpl.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java @@ -25,26 +25,26 @@ import com.hyperwallet.android.ui.common.viewmodel.Event; /** - * {@link ReceiptRepository} implementation + * {@link UserReceiptRepository} implementation */ -public class ReceiptRepositoryImpl implements ReceiptRepository { +public class UserReceiptRepositoryImpl implements UserReceiptRepository { private static final int PAGE_SIZE = 10; private static final int INITIAL_LOAD_SIZE = 20; - private final ReceiptDataSourceFactory mDataSourceFactory; - private final LiveData mReceiptDataSourceLiveData; + private final UserReceiptDataSourceFactory mDataSourceFactory; + private final LiveData mReceiptDataSourceLiveData; private LiveData> mErrorsLiveData; private LiveData mIsFetchingData; private LiveData> mReceiptsLiveData; - ReceiptRepositoryImpl() { - mDataSourceFactory = new ReceiptDataSourceFactory(); - mReceiptDataSourceLiveData = mDataSourceFactory.getReceiptDataSource(); + UserReceiptRepositoryImpl() { + mDataSourceFactory = new UserReceiptDataSourceFactory(); + mReceiptDataSourceLiveData = mDataSourceFactory.getUserReceiptDataSource(); } /** - * @see {@link ReceiptRepository#loadReceipts()} + * @see {@link UserReceiptRepository#loadReceipts()} */ @Override public LiveData> loadReceipts() { @@ -60,7 +60,7 @@ public LiveData> loadReceipts() { } /** - * @see {@link ReceiptRepository#isLoading()} + * @see {@link UserReceiptRepository#isLoading()} */ @Override public LiveData isLoading() { @@ -71,7 +71,7 @@ public LiveData isLoading() { } /** - * @see {@link ReceiptRepository#getErrors()} + * @see {@link UserReceiptRepository#getErrors()} * */ @Override public LiveData> getErrors() { @@ -82,7 +82,7 @@ public LiveData> getErrors() { } /** - * @see {@link ReceiptRepository#retryLoadReceipt()} + * @see {@link UserReceiptRepository#retryLoadReceipt()} * */ @Override public void retryLoadReceipt() { diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index e1fd220a2..0cc0cd856 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -46,7 +46,7 @@ import com.hyperwallet.android.ui.common.util.DateUtils; import com.hyperwallet.android.ui.common.view.OneClickListener; import com.hyperwallet.android.ui.receipt.R; -import com.hyperwallet.android.ui.receipt.viewmodel.ListReceiptViewModel; +import com.hyperwallet.android.ui.receipt.viewmodel.ListUserReceiptViewModel; import java.text.DecimalFormat; import java.util.Calendar; @@ -58,7 +58,7 @@ public class ListReceiptFragment extends Fragment { private ListReceiptAdapter mListReceiptAdapter; private RecyclerView mListReceiptsView; - private ListReceiptViewModel mListReceiptViewModel; + private ListUserReceiptViewModel mListUserReceiptViewModel; private View mProgressBar; /** @@ -78,8 +78,8 @@ static ListReceiptFragment newInstance() { @Override public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mListReceiptViewModel = ViewModelProviders.of(requireActivity()).get( - ListReceiptViewModel.class); + mListUserReceiptViewModel = ViewModelProviders.of(requireActivity()).get( + ListUserReceiptViewModel.class); } @Override @@ -92,7 +92,7 @@ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final 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(mListReceiptViewModel, new ListReceiptItemDiffCallback()); + mListReceiptAdapter = new ListReceiptAdapter(mListUserReceiptViewModel, new ListReceiptItemDiffCallback()); mListReceiptsView = view.findViewById(R.id.list_receipts); mListReceiptsView.setHasFixedSize(true); mListReceiptsView.setLayoutManager(new LinearLayoutManager(getActivity())); @@ -102,14 +102,14 @@ public void onViewCreated(@NonNull final View view, @Nullable final Bundle saved } private void registerObservers() { - mListReceiptViewModel.getReceiptList().observe(getViewLifecycleOwner(), new Observer>() { + mListUserReceiptViewModel.getReceiptList().observe(getViewLifecycleOwner(), new Observer>() { @Override public void onChanged(PagedList receipts) { mListReceiptAdapter.submitList(receipts); } }); - mListReceiptViewModel.isLoadingData().observe(getViewLifecycleOwner(), new Observer() { + mListUserReceiptViewModel.isLoadingData().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(Boolean loading) { if (loading) { @@ -122,7 +122,7 @@ public void onChanged(Boolean loading) { } void retry() { - mListReceiptViewModel.retryLoadReceipts(); + mListUserReceiptViewModel.retryLoadReceipts(); } private static class ListReceiptItemDiffCallback extends DiffUtil.ItemCallback { @@ -146,9 +146,9 @@ private static class ListReceiptAdapter static final String AMOUNT_FORMAT = "###0.00"; private static final int HEADER_VIEW_TYPE = 1; private static final int DATA_VIEW_TYPE = 0; - private final ListReceiptViewModel mReceiptViewModel; + private final ListUserReceiptViewModel mReceiptViewModel; - ListReceiptAdapter(@NonNull final ListReceiptViewModel receiptViewModel, + ListReceiptAdapter(@NonNull final ListUserReceiptViewModel receiptViewModel, @NonNull final DiffUtil.ItemCallback diffCallback) { super(diffCallback); mReceiptViewModel = receiptViewModel; @@ -199,21 +199,21 @@ public void onBindViewHolder(@NonNull final ReceiptViewHolder holder, final int class ReceiptViewHolder extends RecyclerView.ViewHolder { - private ListReceiptViewModel mListReceiptViewModel; + private ListUserReceiptViewModel mListUserReceiptViewModel; private View mView; - ReceiptViewHolder(@NonNull final ListReceiptViewModel receiptViewModel, + ReceiptViewHolder(@NonNull final ListUserReceiptViewModel receiptViewModel, @NonNull final View item) { super(item); mView = item.findViewById(R.id.receipt_item); - mListReceiptViewModel = receiptViewModel; + mListUserReceiptViewModel = receiptViewModel; } void bind(@NonNull final Receipt receipt) { mView.setOnClickListener(new OneClickListener() { @Override public void onOneClick(View v) { - mListReceiptViewModel.setDetailNavigation(receipt); + mListUserReceiptViewModel.setDetailNavigation(receipt); } }); @@ -274,7 +274,7 @@ class ReceiptViewHolderWithHeader extends ReceiptViewHolder { private final TextView mTransactionHeaderText; - ReceiptViewHolderWithHeader(@NonNull final ListReceiptViewModel receiptViewModel, + ReceiptViewHolderWithHeader(@NonNull final ListUserReceiptViewModel receiptViewModel, @NonNull final View item) { super(receiptViewModel, item); mTransactionHeaderText = item.findViewById(R.id.item_date_header_title); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java similarity index 84% rename from receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptActivity.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java index ef56fa89b..c00445ec7 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java @@ -38,20 +38,20 @@ import com.hyperwallet.android.ui.common.viewmodel.Event; import com.hyperwallet.android.ui.common.viewmodel.ListDetailNavigator; import com.hyperwallet.android.ui.receipt.R; -import com.hyperwallet.android.ui.receipt.repository.ReceiptRepositoryFactory; -import com.hyperwallet.android.ui.receipt.viewmodel.ListReceiptViewModel; +import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepositoryFactory; +import com.hyperwallet.android.ui.receipt.viewmodel.ListUserReceiptViewModel; import java.util.List; -public class ListReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback, +public class ListUserReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback, ListDetailNavigator> { - private ListReceiptViewModel mListReceiptViewModel; + private ListUserReceiptViewModel mListUserReceiptViewModel; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_list_receipt); + setContentView(R.layout.activity_list_user_receipt); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); @@ -65,12 +65,12 @@ public void onClick(View v) { } }); - ReceiptRepositoryFactory factory = ReceiptRepositoryFactory.getInstance(); - mListReceiptViewModel = ViewModelProviders.of(this, new ListReceiptViewModel - .ListReceiptViewModelFactory(factory.getReceiptRepository())) - .get(ListReceiptViewModel.class); + UserReceiptRepositoryFactory factory = UserReceiptRepositoryFactory.getInstance(); + mListUserReceiptViewModel = ViewModelProviders.of(this, new ListUserReceiptViewModel + .ListReceiptViewModelFactory(factory.getUserReceiptRepository())) + .get(ListUserReceiptViewModel.class); - mListReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { + mListUserReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { @Override public void onChanged(Event event) { if (event != null && !event.isContentConsumed()) { @@ -79,7 +79,7 @@ public void onChanged(Event event) { } }); - mListReceiptViewModel.getDetailNavigation().observe(this, new Observer>() { + mListUserReceiptViewModel.getDetailNavigation().observe(this, new Observer>() { @Override public void onChanged(Event event) { navigate(event); @@ -94,7 +94,7 @@ public void onChanged(Event event) { @Override protected void onDestroy() { super.onDestroy(); - ReceiptRepositoryFactory.clearInstance(); + UserReceiptRepositoryFactory.clearInstance(); } @Override diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java similarity index 69% rename from receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListReceiptViewModel.java rename to receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java index 0d1533a58..e423275f6 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListReceiptViewModel.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java @@ -27,19 +27,19 @@ import com.hyperwallet.android.model.HyperwalletErrors; import com.hyperwallet.android.model.receipt.Receipt; import com.hyperwallet.android.ui.common.viewmodel.Event; -import com.hyperwallet.android.ui.receipt.repository.ReceiptRepository; +import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepository; -public class ListReceiptViewModel extends ViewModel { +public class ListUserReceiptViewModel extends ViewModel { private MutableLiveData> mErrorEvent = new MutableLiveData<>(); private MutableLiveData> mDetailNavigation = new MutableLiveData<>(); private Observer> mErrorEventObserver; - private ReceiptRepository mReceiptRepository; + private UserReceiptRepository mUserReceiptRepository; - private ListReceiptViewModel(@NonNull final ReceiptRepository receiptRepository) { - mReceiptRepository = receiptRepository; + private ListUserReceiptViewModel(@NonNull final UserReceiptRepository userReceiptRepository) { + mUserReceiptRepository = userReceiptRepository; // load initial receipts - mReceiptRepository.loadReceipts(); + mUserReceiptRepository.loadReceipts(); // register one time error event observer mErrorEventObserver = new Observer>() { @@ -48,11 +48,11 @@ public void onChanged(Event event) { mErrorEvent.postValue(event); } }; - mReceiptRepository.getErrors().observeForever(mErrorEventObserver); + mUserReceiptRepository.getErrors().observeForever(mErrorEventObserver); } public LiveData isLoadingData() { - return mReceiptRepository.isLoading(); + return mUserReceiptRepository.isLoading(); } public LiveData> getReceiptErrors() { @@ -60,11 +60,11 @@ public LiveData> getReceiptErrors() { } public LiveData> getReceiptList() { - return mReceiptRepository.loadReceipts(); + return mUserReceiptRepository.loadReceipts(); } public void retryLoadReceipts() { - mReceiptRepository.retryLoadReceipt(); + mUserReceiptRepository.retryLoadReceipt(); } public LiveData> getDetailNavigation() { @@ -78,25 +78,26 @@ public void setDetailNavigation(@NonNull final Receipt receipt) { @Override protected void onCleared() { super.onCleared(); - mReceiptRepository.getErrors().removeObserver(mErrorEventObserver); - mReceiptRepository = null; + mUserReceiptRepository.getErrors().removeObserver(mErrorEventObserver); + mUserReceiptRepository = null; } public static class ListReceiptViewModelFactory implements ViewModelProvider.Factory { - private final ReceiptRepository mReceiptRepository; + private final UserReceiptRepository mUserReceiptRepository; - public ListReceiptViewModelFactory(@NonNull final ReceiptRepository receiptRepository) { - mReceiptRepository = receiptRepository; + public ListReceiptViewModelFactory(@NonNull final UserReceiptRepository userReceiptRepository) { + mUserReceiptRepository = userReceiptRepository; } @NonNull @Override public T create(@NonNull Class modelClass) { - if (modelClass.isAssignableFrom(ListReceiptViewModel.class)) { - return (T) new ListReceiptViewModel(mReceiptRepository); + if (modelClass.isAssignableFrom(ListUserReceiptViewModel.class)) { + return (T) new ListUserReceiptViewModel(mUserReceiptRepository); } - throw new IllegalArgumentException("Expecting ViewModel class: " + ListReceiptViewModel.class.getName()); + throw new IllegalArgumentException( + "Expecting ViewModel class: " + ListUserReceiptViewModel.class.getName()); } } } diff --git a/receipt/src/main/res/layout/activity_list_receipt.xml b/receipt/src/main/res/layout/activity_list_user_receipt.xml similarity index 91% rename from receipt/src/main/res/layout/activity_list_receipt.xml rename to receipt/src/main/res/layout/activity_list_user_receipt.xml index 44beb1444..2eb8c57ac 100644 --- a/receipt/src/main/res/layout/activity_list_receipt.xml +++ b/receipt/src/main/res/layout/activity_list_user_receipt.xml @@ -5,7 +5,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".view.ListReceiptActivity"> + tools:context=".view.ListUserReceiptActivity"> + tools:context=".view.ListUserReceiptActivity" + tools:showIn="@layout/activity_list_user_receipt"/> \ No newline at end of file diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactoryTest.java deleted file mode 100644 index 714becb62..000000000 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactoryTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.hyperwallet.android.ui.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/ui/receipt/repository/ReceiptDataSourceFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactoryTest.java similarity index 72% rename from receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactoryTest.java rename to receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactoryTest.java index b8a6974f2..feb62a3a2 100644 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceFactoryTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactoryTest.java @@ -13,14 +13,14 @@ import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) -public class ReceiptDataSourceFactoryTest { +public class UserReceiptDataSourceFactoryTest { @Test public void testGetReceiptDataSource_returnsLiveDataReceiptSource() { // initialize - ReceiptDataSourceFactory dataSourceFactory = new ReceiptDataSourceFactory(); + UserReceiptDataSourceFactory dataSourceFactory = new UserReceiptDataSourceFactory(); // test - LiveData liveData = dataSourceFactory.getReceiptDataSource(); + LiveData liveData = dataSourceFactory.getUserReceiptDataSource(); // assert assertThat(liveData, is(notNullValue())); } @@ -28,11 +28,11 @@ public void testGetReceiptDataSource_returnsLiveDataReceiptSource() { @Test public void testCreate_returnsDataSource() { // initialize - ReceiptDataSourceFactory dataSourceFactory = new ReceiptDataSourceFactory(); + UserReceiptDataSourceFactory dataSourceFactory = new UserReceiptDataSourceFactory(); // test DataSource dataSource = dataSourceFactory.create(); // assert assertThat(dataSource, is(notNullValue())); - assertThat(dataSource, CoreMatchers.instanceOf(ReceiptDataSource.class)); + assertThat(dataSource, CoreMatchers.instanceOf(UserReceiptDataSource.class)); } } diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceTest.java similarity index 85% rename from receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java rename to receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceTest.java index 50aa0ad5e..e61646e32 100644 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSourceTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceTest.java @@ -50,7 +50,7 @@ import java.util.List; @RunWith(RobolectricTestRunner.class) -public class ReceiptDataSourceTest { +public class UserReceiptDataSourceTest { @Rule public MockitoRule mMockito = MockitoJUnit.rule(); @@ -77,11 +77,11 @@ public class ReceiptDataSourceTest { private ArgumentCaptor mNextCaptor; @Spy - private ReceiptDataSource mReceiptDataSource; + private UserReceiptDataSource mUserReceiptDataSource; @Before public void setUp() { - doReturn(mHyperwallet).when(mReceiptDataSource).getHyperwallet(); + doReturn(mHyperwallet).when(mUserReceiptDataSource).getHyperwallet(); } @Test @@ -100,7 +100,7 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + mUserReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); @@ -136,8 +136,8 @@ public Object answer(InvocationOnMock invocation) { 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)); + assertThat(mUserReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mUserReceiptDataSource.isFetchingData().getValue(), is(false)); } @Test @@ -153,14 +153,14 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + mUserReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); verify(mHyperwallet).listUserReceipts(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)); + assertThat(mUserReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mUserReceiptDataSource.isFetchingData().getValue(), is(false)); } @Test @@ -181,20 +181,20 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + mUserReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); verify(mHyperwallet).listUserReceipts(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(), + assertThat(mUserReceiptDataSource.getErrors().getValue(), is(notNullValue())); + assertThat(mUserReceiptDataSource.getErrors().getValue().getContent().getErrors(), Matchers.hasSize(1)); - assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), + assertThat(mUserReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), is("TEST_CODE")); - assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), + assertThat(mUserReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), is("test message")); - assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + assertThat(mUserReceiptDataSource.isFetchingData().getValue(), is(false)); } @Test @@ -215,23 +215,23 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + mUserReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); verify(mHyperwallet).listUserReceipts(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())); + assertThat(mUserReceiptDataSource.getErrors().getValue(), is(notNullValue())); // test retry, saved params and callback will be used and no null pointer exception is thrown - mReceiptDataSource.retry(); + mUserReceiptDataSource.retry(); // verify calls - verify(mReceiptDataSource, times(2)).loadInitial( + verify(mUserReceiptDataSource, times(2)).loadInitial( ArgumentMatchers.>any(), ArgumentMatchers.>any()); - verify(mReceiptDataSource, never()).loadAfter( + verify(mUserReceiptDataSource, never()).loadAfter( ArgumentMatchers.>any(), ArgumentMatchers.>any()); } @@ -252,7 +252,7 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + mUserReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); @@ -286,8 +286,8 @@ public Object answer(InvocationOnMock invocation) { 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)); + assertThat(mUserReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mUserReceiptDataSource.isFetchingData().getValue(), is(false)); } @Test @@ -303,14 +303,14 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + mUserReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); verify(mHyperwallet).listUserReceipts(any(ReceiptQueryParam.class), ArgumentMatchers.>>any()); verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.>any(), anyInt()); - assertThat(mReceiptDataSource.getErrors().getValue(), is(nullValue())); - assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + assertThat(mUserReceiptDataSource.getErrors().getValue(), is(nullValue())); + assertThat(mUserReceiptDataSource.isFetchingData().getValue(), is(false)); } @Test @@ -331,21 +331,21 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + mUserReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); verify(mHyperwallet).listUserReceipts(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(), + assertThat(mUserReceiptDataSource.getErrors().getValue(), is(notNullValue())); + assertThat(mUserReceiptDataSource.getErrors().getValue().getContent().getErrors(), Matchers.hasSize(1)); - assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), + assertThat(mUserReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), is("LOAD_AFTER_CODE")); - assertThat(mReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), + assertThat(mUserReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), is("test message load after")); - assertThat(mReceiptDataSource.isFetchingData().getValue(), is(false)); + assertThat(mUserReceiptDataSource.isFetchingData().getValue(), is(false)); } @Test @@ -366,23 +366,23 @@ public Object answer(InvocationOnMock invocation) { ArgumentMatchers.>>any()); // test - mReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + mUserReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); verify(mHyperwallet).listUserReceipts(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(mUserReceiptDataSource.getErrors().getValue(), is(notNullValue())); // test retry, saved params and callback will be used and no null pointer exception is thrown - mReceiptDataSource.retry(); + mUserReceiptDataSource.retry(); // verify calls - verify(mReceiptDataSource, times(2)).loadAfter( + verify(mUserReceiptDataSource, times(2)).loadAfter( ArgumentMatchers.>any(), ArgumentMatchers.>any()); - verify(mReceiptDataSource, never()).loadInitial( + verify(mUserReceiptDataSource, never()).loadInitial( ArgumentMatchers.>any(), ArgumentMatchers.>any()); } diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java new file mode 100644 index 000000000..7ea7c604f --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java @@ -0,0 +1,39 @@ +package com.hyperwallet.android.ui.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 UserReceiptRepositoryFactoryTest { + + @Test + public void testGetInstance_verifyRepositoriesInitialized() { + // test + UserReceiptRepositoryFactory factory = UserReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(notNullValue())); + assertThat(factory.getUserReceiptRepository(), is(notNullValue())); + + UserReceiptRepositoryFactory factory2 = UserReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(factory2)); + assertThat(factory.getUserReceiptRepository(), is(factory2.getUserReceiptRepository())); + } + + @Test + public void testClearInstance_verifyRepositoriesCleared() { + UserReceiptRepositoryFactory factory = UserReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(notNullValue())); + assertThat(factory.getUserReceiptRepository(), is(notNullValue())); + + // test clear + UserReceiptRepositoryFactory.clearInstance(); + UserReceiptRepositoryFactory factory2 = UserReceiptRepositoryFactory.getInstance(); + assertThat(factory, is(not(factory2))); + assertThat(factory.getUserReceiptRepository(), is(not(factory2.getUserReceiptRepository()))); + } +} 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 b47c1f87d..21850b5b9 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.ui.receipt.view.ListReceiptActivity; +import com.hyperwallet.android.ui.receipt.view.ListUserReceiptActivity; import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; import com.hyperwallet.android.ui.transfermethod.ListTransferMethodActivity; import com.hyperwallet.android.ui.transfermethod.SelectTransferMethodActivity; @@ -81,10 +81,10 @@ public Intent getIntentSelectTransferMethodActivity(@NonNull final Context conte /** * @param context A Context of the application consuming this Intent. - * @return an Intent with the data necessary to launch the {@link ListReceiptActivity} + * @return an Intent with the data necessary to launch the {@link ListUserReceiptActivity} */ public Intent getIntentListReceiptActivity(@NonNull final Context context) { - return new Intent(context, ListReceiptActivity.class); + return new Intent(context, ListUserReceiptActivity.class); } /** @@ -107,6 +107,4 @@ public Intent getIntentAddTransferMethodActivity(@NonNull final Context context, intent.putExtra(EXTRA_TRANSFER_METHOD_PROFILE_TYPE, profileType); return intent; } - - } From 680b4c6c06233526af10c319fadd3272d8e138d0 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 19 Jun 2019 07:50:28 -0700 Subject: [PATCH 25/36] changed singletone to immutable data source factory --- .../ui/receipt/ListUserReceiptsTest.java | 6 -- .../UserReceiptRepositoryFactory.java | 56 ------------------- .../repository/UserReceiptRepositoryImpl.java | 2 +- .../receipt/view/ListUserReceiptActivity.java | 11 +--- .../UserReceiptRepositoryFactoryTest.java | 39 ------------- 5 files changed, 3 insertions(+), 111 deletions(-) delete mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactory.java delete mode 100644 receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java index 3502cf704..5ff5bf299 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java @@ -41,7 +41,6 @@ import com.hyperwallet.android.Hyperwallet; import com.hyperwallet.android.ui.common.util.DateUtils; import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; -import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepositoryFactory; import com.hyperwallet.android.ui.receipt.rule.HyperwalletExternalResourceManager; import com.hyperwallet.android.ui.receipt.rule.HyperwalletMockWebServer; import com.hyperwallet.android.ui.receipt.util.RecyclerViewCountAssertion; @@ -82,11 +81,6 @@ public void setup() { setLocale(Locale.US); } - @After - public void cleanup() { - UserReceiptRepositoryFactory.clearInstance(); - } - @Before public void registerIdlingResource() { IdlingRegistry.getInstance().register(EspressoIdlingResource.getIdlingResource()); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactory.java deleted file mode 100644 index 8afc69437..000000000 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactory.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.ui.receipt.repository; - -/** - * {@link UserReceiptRepository} factory - */ -public class UserReceiptRepositoryFactory { - - private static UserReceiptRepositoryFactory sInstance; - private final UserReceiptRepository mUserReceiptRepository; - - private UserReceiptRepositoryFactory() { - mUserReceiptRepository = new UserReceiptRepositoryImpl(); - } - - /** - * Creates context single instance of this Factory - * - * @return receipt repository factory instance - */ - public static synchronized UserReceiptRepositoryFactory getInstance() { - if (sInstance == null) { - sInstance = new UserReceiptRepositoryFactory(); - } - return sInstance; - } - - /** - * Clears instance of repository factory - */ - public static void clearInstance() { - sInstance = null; - } - - /** - * @return UserReceiptRepository instance implementation - * */ - public UserReceiptRepository getUserReceiptRepository() { - return mUserReceiptRepository; - } -} diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java index 864d13b2e..f15f9147f 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java @@ -38,7 +38,7 @@ public class UserReceiptRepositoryImpl implements UserReceiptRepository { private LiveData mIsFetchingData; private LiveData> mReceiptsLiveData; - UserReceiptRepositoryImpl() { + public UserReceiptRepositoryImpl() { mDataSourceFactory = new UserReceiptDataSourceFactory(); mReceiptDataSourceLiveData = mDataSourceFactory.getUserReceiptDataSource(); } diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java index c00445ec7..c4877c1a9 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java @@ -38,7 +38,7 @@ import com.hyperwallet.android.ui.common.viewmodel.Event; import com.hyperwallet.android.ui.common.viewmodel.ListDetailNavigator; import com.hyperwallet.android.ui.receipt.R; -import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepositoryFactory; +import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepositoryImpl; import com.hyperwallet.android.ui.receipt.viewmodel.ListUserReceiptViewModel; import java.util.List; @@ -65,9 +65,8 @@ public void onClick(View v) { } }); - UserReceiptRepositoryFactory factory = UserReceiptRepositoryFactory.getInstance(); mListUserReceiptViewModel = ViewModelProviders.of(this, new ListUserReceiptViewModel - .ListReceiptViewModelFactory(factory.getUserReceiptRepository())) + .ListReceiptViewModelFactory(new UserReceiptRepositoryImpl())) .get(ListUserReceiptViewModel.class); mListUserReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { @@ -91,12 +90,6 @@ public void onChanged(Event event) { } } - @Override - protected void onDestroy() { - super.onDestroy(); - UserReceiptRepositoryFactory.clearInstance(); - } - @Override protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { super.onActivityResult(requestCode, resultCode, data); diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java deleted file mode 100644 index 7ea7c604f..000000000 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryFactoryTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.hyperwallet.android.ui.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 UserReceiptRepositoryFactoryTest { - - @Test - public void testGetInstance_verifyRepositoriesInitialized() { - // test - UserReceiptRepositoryFactory factory = UserReceiptRepositoryFactory.getInstance(); - assertThat(factory, is(notNullValue())); - assertThat(factory.getUserReceiptRepository(), is(notNullValue())); - - UserReceiptRepositoryFactory factory2 = UserReceiptRepositoryFactory.getInstance(); - assertThat(factory, is(factory2)); - assertThat(factory.getUserReceiptRepository(), is(factory2.getUserReceiptRepository())); - } - - @Test - public void testClearInstance_verifyRepositoriesCleared() { - UserReceiptRepositoryFactory factory = UserReceiptRepositoryFactory.getInstance(); - assertThat(factory, is(notNullValue())); - assertThat(factory.getUserReceiptRepository(), is(notNullValue())); - - // test clear - UserReceiptRepositoryFactory.clearInstance(); - UserReceiptRepositoryFactory factory2 = UserReceiptRepositoryFactory.getInstance(); - assertThat(factory, is(not(factory2))); - assertThat(factory.getUserReceiptRepository(), is(not(factory2.getUserReceiptRepository()))); - } -} From 0f5e5d5c45491d57353ab493350f74f8e4a638ac Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 19 Jun 2019 08:17:05 -0700 Subject: [PATCH 26/36] generalized view model so that we can reuse the user receipt view for ppc receipt presentation --- .../ui/receipt/view/ListReceiptFragment.java | 23 ++++---- .../receipt/view/ListUserReceiptActivity.java | 9 +-- .../viewmodel/ListUserReceiptViewModel.java | 2 +- .../receipt/viewmodel/ReceiptViewModel.java | 59 +++++++++++++++++++ 4 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ReceiptViewModel.java diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index 0cc0cd856..51075c28d 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -47,6 +47,7 @@ import com.hyperwallet.android.ui.common.view.OneClickListener; import com.hyperwallet.android.ui.receipt.R; import com.hyperwallet.android.ui.receipt.viewmodel.ListUserReceiptViewModel; +import com.hyperwallet.android.ui.receipt.viewmodel.ReceiptViewModel; import java.text.DecimalFormat; import java.util.Calendar; @@ -58,7 +59,7 @@ public class ListReceiptFragment extends Fragment { private ListReceiptAdapter mListReceiptAdapter; private RecyclerView mListReceiptsView; - private ListUserReceiptViewModel mListUserReceiptViewModel; + private ReceiptViewModel mReceiptViewModel; private View mProgressBar; /** @@ -78,7 +79,7 @@ static ListReceiptFragment newInstance() { @Override public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mListUserReceiptViewModel = ViewModelProviders.of(requireActivity()).get( + mReceiptViewModel = ViewModelProviders.of(requireActivity()).get( ListUserReceiptViewModel.class); } @@ -92,7 +93,7 @@ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final 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(mListUserReceiptViewModel, new ListReceiptItemDiffCallback()); + mListReceiptAdapter = new ListReceiptAdapter(mReceiptViewModel, new ListReceiptItemDiffCallback()); mListReceiptsView = view.findViewById(R.id.list_receipts); mListReceiptsView.setHasFixedSize(true); mListReceiptsView.setLayoutManager(new LinearLayoutManager(getActivity())); @@ -102,14 +103,14 @@ public void onViewCreated(@NonNull final View view, @Nullable final Bundle saved } private void registerObservers() { - mListUserReceiptViewModel.getReceiptList().observe(getViewLifecycleOwner(), new Observer>() { + mReceiptViewModel.getReceiptList().observe(getViewLifecycleOwner(), new Observer>() { @Override public void onChanged(PagedList receipts) { mListReceiptAdapter.submitList(receipts); } }); - mListUserReceiptViewModel.isLoadingData().observe(getViewLifecycleOwner(), new Observer() { + mReceiptViewModel.isLoadingData().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(Boolean loading) { if (loading) { @@ -122,7 +123,7 @@ public void onChanged(Boolean loading) { } void retry() { - mListUserReceiptViewModel.retryLoadReceipts(); + mReceiptViewModel.retryLoadReceipts(); } private static class ListReceiptItemDiffCallback extends DiffUtil.ItemCallback { @@ -146,9 +147,9 @@ private static class ListReceiptAdapter static final String AMOUNT_FORMAT = "###0.00"; private static final int HEADER_VIEW_TYPE = 1; private static final int DATA_VIEW_TYPE = 0; - private final ListUserReceiptViewModel mReceiptViewModel; + private final ReceiptViewModel mReceiptViewModel; - ListReceiptAdapter(@NonNull final ListUserReceiptViewModel receiptViewModel, + ListReceiptAdapter(@NonNull final ReceiptViewModel receiptViewModel, @NonNull final DiffUtil.ItemCallback diffCallback) { super(diffCallback); mReceiptViewModel = receiptViewModel; @@ -199,10 +200,10 @@ public void onBindViewHolder(@NonNull final ReceiptViewHolder holder, final int class ReceiptViewHolder extends RecyclerView.ViewHolder { - private ListUserReceiptViewModel mListUserReceiptViewModel; + private ReceiptViewModel mListUserReceiptViewModel; private View mView; - ReceiptViewHolder(@NonNull final ListUserReceiptViewModel receiptViewModel, + ReceiptViewHolder(@NonNull final ReceiptViewModel receiptViewModel, @NonNull final View item) { super(item); mView = item.findViewById(R.id.receipt_item); @@ -274,7 +275,7 @@ class ReceiptViewHolderWithHeader extends ReceiptViewHolder { private final TextView mTransactionHeaderText; - ReceiptViewHolderWithHeader(@NonNull final ListUserReceiptViewModel receiptViewModel, + ReceiptViewHolderWithHeader(@NonNull final ReceiptViewModel receiptViewModel, @NonNull final View item) { super(receiptViewModel, item); mTransactionHeaderText = item.findViewById(R.id.item_date_header_title); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java index c4877c1a9..e97acf5c9 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java @@ -40,13 +40,14 @@ import com.hyperwallet.android.ui.receipt.R; import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepositoryImpl; import com.hyperwallet.android.ui.receipt.viewmodel.ListUserReceiptViewModel; +import com.hyperwallet.android.ui.receipt.viewmodel.ReceiptViewModel; import java.util.List; public class ListUserReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback, ListDetailNavigator> { - private ListUserReceiptViewModel mListUserReceiptViewModel; + private ReceiptViewModel mReceiptViewModel; @Override protected void onCreate(final Bundle savedInstanceState) { @@ -65,11 +66,11 @@ public void onClick(View v) { } }); - mListUserReceiptViewModel = ViewModelProviders.of(this, new ListUserReceiptViewModel + mReceiptViewModel = ViewModelProviders.of(this, new ListUserReceiptViewModel .ListReceiptViewModelFactory(new UserReceiptRepositoryImpl())) .get(ListUserReceiptViewModel.class); - mListUserReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { + mReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { @Override public void onChanged(Event event) { if (event != null && !event.isContentConsumed()) { @@ -78,7 +79,7 @@ public void onChanged(Event event) { } }); - mListUserReceiptViewModel.getDetailNavigation().observe(this, new Observer>() { + mReceiptViewModel.getDetailNavigation().observe(this, new Observer>() { @Override public void onChanged(Event event) { navigate(event); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java index e423275f6..5fefdf153 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java @@ -29,7 +29,7 @@ import com.hyperwallet.android.ui.common.viewmodel.Event; import com.hyperwallet.android.ui.receipt.repository.UserReceiptRepository; -public class ListUserReceiptViewModel extends ViewModel { +public class ListUserReceiptViewModel extends ReceiptViewModel { private MutableLiveData> mErrorEvent = new MutableLiveData<>(); private MutableLiveData> mDetailNavigation = new MutableLiveData<>(); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ReceiptViewModel.java new file mode 100644 index 000000000..f100b86bc --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ReceiptViewModel.java @@ -0,0 +1,59 @@ +/* + * 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.ui.receipt.viewmodel; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; +import androidx.paging.PagedList; + +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.ui.common.viewmodel.Event; + +public abstract class ReceiptViewModel extends ViewModel { + + /** + * @return live data of isloading information + */ + public abstract LiveData isLoadingData(); + + /** + * @return live data of receipt errors {@link HyperwalletErrors} + */ + public abstract LiveData> getReceiptErrors(); + + /** + * @return paged live data of receipts {@link Receipt} + */ + public abstract LiveData> getReceiptList(); + + /** + * Explicit invoke of load retry on receipts data + */ + public abstract void retryLoadReceipts(); + + /** + * @return binding live data of detail navigation information + */ + public abstract LiveData> getDetailNavigation(); + + /** + * @param receipt {@link Receipt} object to set on navigating to Receipt details view + */ + public abstract void setDetailNavigation(@NonNull final Receipt receipt); +} From 4082b82a94c44a63edbcb598719301a42061eee5 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 19 Jun 2019 10:37:15 -0700 Subject: [PATCH 27/36] added data source for prepaid card and test equivalent unit test --- .../PrepaidCardReceiptDataSource.java | 205 +++++++++ .../repository/UserReceiptDataSource.java | 2 +- .../PrepaidCardReceiptDataSourceTest.java | 396 ++++++++++++++++++ 3 files changed, 602 insertions(+), 1 deletion(-) create mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java create mode 100644 receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java new file mode 100644 index 000000000..16bddfc64 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java @@ -0,0 +1,205 @@ +/* + * 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.ui.receipt.repository; + +import android.os.Handler; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +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.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 com.hyperwallet.android.util.DateUtil; + +import java.util.Calendar; +import java.util.Date; + +/** + * PrepaidCardReceiptDataSource mediates communication to HW API Platform particularly on + * Receipts PrepaidCard V3 API + */ +public class PrepaidCardReceiptDataSource extends PageKeyedDataSource { + + private static final int YEAR_BEFORE_NOW = -1; + + private final Calendar mCalendarYearBeforeNow; + private final String mToken; + private final MutableLiveData> mErrors = new MutableLiveData<>(); + private final MutableLiveData mIsFetchingData = new MutableLiveData<>(); + private PageKeyedDataSource.LoadCallback mLoadAfterCallback; + private PageKeyedDataSource.LoadParams mLoadAfterParams; + private PageKeyedDataSource.LoadInitialCallback mLoadInitialCallback; + private PageKeyedDataSource.LoadInitialParams mLoadInitialParams; + + @VisibleForTesting + PrepaidCardReceiptDataSource() { + mCalendarYearBeforeNow = Calendar.getInstance(); + mCalendarYearBeforeNow.add(Calendar.YEAR, YEAR_BEFORE_NOW); + mToken = "trm-test-token"; + } + + /** + * Initialize Prepaid card data source + * + * @param token Prepaid card token identifier, please get this data from HW Platform + */ + public PrepaidCardReceiptDataSource(@NonNull final String token) { + mToken = token; + 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()) + .sortByCreatedOnDesc().build(); + + getHyperwallet().listPrepaidCardReceipts(mToken, queryParam, + new HyperwalletListener>() { + @Override + public void onSuccess(@Nullable HyperwalletPageList result) { + mIsFetchingData.postValue(Boolean.FALSE); + mErrors.postValue(null); + + if (result != null) { + callback.onResult(result.getDataList(), mCalendarYearBeforeNow.getTime(), null); + } + + // 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; + } + }); + } + + /** + * @see {@link PageKeyedDataSource#loadBefore(LoadParams, LoadCallback)} + */ + @Override + public void loadBefore(@NonNull final LoadParams params, + @NonNull final LoadCallback callback) { + } + + /** + * @see {@link PageKeyedDataSource#loadAfter(LoadParams, LoadCallback)} + */ + @Override + public void loadAfter(@NonNull final LoadParams params, @NonNull final LoadCallback callback) { + mLoadAfterCallback = callback; + mLoadAfterParams = params; + + ReceiptQueryParam queryParam = new ReceiptQueryParam.Builder() + .createdAfter(params.key) + .limit(params.requestedLoadSize) + .sortByCreatedOnDesc().build(); + + getHyperwallet().listPrepaidCardReceipts(mToken, queryParam, + new HyperwalletListener>() { + @Override + public void onSuccess(@Nullable HyperwalletPageList result) { + mIsFetchingData.postValue(Boolean.FALSE); + mErrors.postValue(null); + + if (result != null) { + callback.onResult(result.getDataList(), getNextDate(result)); + } + + // 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(); + } + + private Date getNextDate(@Nullable final HyperwalletPageList result) { + if (result != null && result.getDataList() != null && !result.getDataList().isEmpty()) { + // get last receipt date + return DateUtil.fromDateTimeString( + result.getDataList().get(result.getDataList().size() - 1).getCreatedOn()); + } + return Calendar.getInstance().getTime(); + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java index d281e656e..766dc4c1e 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java @@ -38,7 +38,7 @@ /** * UserReceiptDataSource mediates communication to HW API Platform particularly on - * Receipts V3 API + * Receipts Users V3 API */ public class UserReceiptDataSource extends PageKeyedDataSource { diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java new file mode 100644 index 000000000..90a00eed5 --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java @@ -0,0 +1,396 @@ +package com.hyperwallet.android.ui.receipt.repository; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +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.ReceiptTypes.ADJUSTMENT; +import static com.hyperwallet.android.model.receipt.Receipt.ReceiptTypes.DEPOSIT; + +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 com.hyperwallet.android.util.DateUtil; + +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.Date; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class PrepaidCardReceiptDataSourceTest { + + @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<>( + new Date(), 10); + @Mock + private PageKeyedDataSource.LoadCallback mLoadAfterCallback; + + @Captor + private ArgumentCaptor> mListArgumentCaptor; + @Captor + private ArgumentCaptor mPreviousCaptor; + @Captor + private ArgumentCaptor mNextCaptor; + + @Spy + private PrepaidCardReceiptDataSource mPrepaidCardReceiptDataSource; + + @Before + public void setUp() { + doReturn(mHyperwallet).when(mPrepaidCardReceiptDataSource).getHyperwallet(); + } + + + @Test + public void testLoadInitial_returnsReceipts() throws Exception { + String json = mExternalResourceManager.getResourceContent("ppc_receipt_list.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()[2]; + listener.onSuccess(response); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback).onResult(mListArgumentCaptor.capture(), mPreviousCaptor.capture(), + mNextCaptor.capture()); + + assertThat(mPreviousCaptor.getValue(), is(notNullValue())); + assertThat(mNextCaptor.getValue(), is(nullValue())); + + // assert receipts information + List receipts = mListArgumentCaptor.getValue(); + assertThat(receipts, Matchers.hasSize(7)); + assertThat(receipts.get(0).getJournalId(), is("FISVL_5240220")); + assertThat(receipts.get(0).getType(), is(DEPOSIT)); + assertThat(receipts.get(0).getCreatedOn(), is("2019-06-06T22:48:41")); + assertThat(receipts.get(0).getEntry(), is(CREDIT)); + assertThat(receipts.get(0).getDestinationToken(), is("trm-2e02da75-a36c-4723-b613-0b64e6f582d9")); + assertThat(receipts.get(0).getAmount(), is("10.00")); + assertThat(receipts.get(0).getCurrency(), is("USD")); + assertThat(receipts.get(0).getDetails(), is(notNullValue())); + assertThat(receipts.get(0).getDetails().getCardNumber(), is("************0673")); + assertThat(receipts.get(6).getJournalId(), is("FISA_5240226")); + assertThat(receipts.get(6).getType(), is(ADJUSTMENT)); + assertThat(receipts.get(6).getCreatedOn(), is("2019-02-21T23:55:17")); + assertThat(receipts.get(6).getEntry(), is(CREDIT)); + assertThat(receipts.get(6).getSourceToken(), is("trm-2e02da75-a36c-4723-b613-0b64e6f582d9")); + assertThat(receipts.get(6).getAmount(), is("9.92")); + assertThat(receipts.get(6).getCurrency(), is("USD")); + assertThat(receipts.get(6).getDetails(), is(notNullValue())); + assertThat(receipts.get(6).getDetails().getCardNumber(), is("************0673")); + + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(Matchers.nullValue())); + assertThat(mPrepaidCardReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testLoadInitial_returnNoReceipt() { + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[2]; + listener.onSuccess(null); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), any(Date.class), + any(Date.class)); + + // assert + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(Matchers.nullValue())); + assertThat(mPrepaidCardReceiptDataSource.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()[2]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), any(Date.class), + any(Date.class)); + + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(notNullValue())); + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue().getContent().getErrors(), + Matchers.hasSize(1)); + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), + is("TEST_CODE")); + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), + is("test message")); + assertThat(mPrepaidCardReceiptDataSource.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()[2]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadInitial(mInitialParams, mInitialCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mInitialCallback, never()).onResult(ArgumentMatchers.anyList(), any(Date.class), + any(Date.class)); + + // error occurred, this will save params and callback + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(notNullValue())); + + // test retry + mPrepaidCardReceiptDataSource.retry(); + + // verify calls + verify(mPrepaidCardReceiptDataSource, times(2)).loadInitial( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + verify(mPrepaidCardReceiptDataSource, never()).loadAfter( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + } + + @Test + public void testLoadAfter_returnsReceipts() throws Exception { + String json = mExternalResourceManager.getResourceContent("ppc_receipt_list.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()[2]; + listener.onSuccess(response); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback).onResult(mListArgumentCaptor.capture(), mNextCaptor.capture()); + + // assert receipts information + List receipts = mListArgumentCaptor.getValue(); + assertThat(receipts, Matchers.hasSize(7)); + assertThat(receipts.get(1).getJournalId(), is("FISVL_5240221")); + assertThat(receipts.get(1).getType(), is(DEPOSIT)); + assertThat(receipts.get(1).getCreatedOn(), is("2019-06-06T22:48:51")); + assertThat(receipts.get(1).getEntry(), is(CREDIT)); + assertThat(receipts.get(1).getDestinationToken(), is("trm-2e02da75-a36c-4723-b613-0b64e6f582d9")); + assertThat(receipts.get(1).getAmount(), is("5.00")); + assertThat(receipts.get(1).getCurrency(), is("USD")); + assertThat(receipts.get(1).getDetails(), is(notNullValue())); + assertThat(receipts.get(1).getDetails().getCardNumber(), is("************0673")); + assertThat(receipts.get(5).getJournalId(), is("FISA_5240225")); + assertThat(receipts.get(5).getType(), is(ADJUSTMENT)); + assertThat(receipts.get(5).getCreatedOn(), is("2019-02-23T23:55:17")); + assertThat(receipts.get(5).getEntry(), is(CREDIT)); + assertThat(receipts.get(5).getSourceToken(), is("trm-2e02da75-a36c-4723-b613-0b64e6f582d9")); + assertThat(receipts.get(5).getAmount(), is("3.90")); + assertThat(receipts.get(5).getCurrency(), is("USD")); + assertThat(receipts.get(5).getDetails(), is(notNullValue())); + assertThat(receipts.get(5).getDetails().getCardNumber(), is("************0673")); + + assertThat(mNextCaptor.getValue(), is(DateUtil.fromDateTimeString(receipts.get(6).getCreatedOn()))); + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(Matchers.nullValue())); + assertThat(mPrepaidCardReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testLoadAfter_returnNoReceipt() { + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) { + HyperwalletListener listener = (HyperwalletListener) invocation.getArguments()[2]; + listener.onSuccess(null); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.anyList(), any(Date.class)); + + // assert + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(Matchers.nullValue())); + assertThat(mPrepaidCardReceiptDataSource.isFetchingData().getValue(), is(false)); + } + + @Test + public void testLoadAfter_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()[2]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.anyList(), any(Date.class)); + + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(notNullValue())); + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue().getContent().getErrors(), + Matchers.hasSize(1)); + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getCode(), + is("TEST_CODE")); + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue().getContent().getErrors().get(0).getMessage(), + is("test message")); + assertThat(mPrepaidCardReceiptDataSource.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()[2]; + listener.onFailure(new HyperwalletException(errors)); + return listener; + } + }).when(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + + // test + mPrepaidCardReceiptDataSource.loadAfter(mLoadAfterParams, mLoadAfterCallback); + + // verify + verify(mHyperwallet).listPrepaidCardReceipts(anyString(), any(ReceiptQueryParam.class), + ArgumentMatchers.>>any()); + verify(mLoadAfterCallback, never()).onResult(ArgumentMatchers.anyList(), any(Date.class)); + + // error occurred, this will save params and callback + assertThat(mPrepaidCardReceiptDataSource.getErrors().getValue(), is(notNullValue())); + + // test retry + mPrepaidCardReceiptDataSource.retry(); + + // verify calls + verify(mPrepaidCardReceiptDataSource, never()).loadInitial( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + verify(mPrepaidCardReceiptDataSource, times(2)).loadAfter( + ArgumentMatchers.>any(), + ArgumentMatchers.>any()); + } +} From 109db66b33e003c0410f7eddbe1dff516087b58f Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 19 Jun 2019 15:22:58 -0700 Subject: [PATCH 28/36] initial integration of ppc and user receipts --- receipt/build.gradle | 2 + .../receipt/ListPrepaidCardReceiptsTest.java | 107 +++++++++++++ receipt/src/main/AndroidManifest.xml | 15 +- .../PrepaidCardReceiptDataSourceFactory.java | 53 +++++++ .../PrepaidCardReceiptRepository.java | 55 +++++++ .../PrepaidCardReceiptRepositoryImpl.java | 75 +++++++++ .../UserReceiptDataSourceFactory.java | 4 +- .../repository/UserReceiptRepository.java | 6 +- .../repository/UserReceiptRepositoryImpl.java | 4 +- .../view/ListPrepaidCardReceiptActivity.java | 143 ++++++++++++++++++ .../ui/receipt/view/ListReceiptFragment.java | 3 +- .../receipt/view/ListUserReceiptActivity.java | 2 +- .../ListPrepaidCardReceiptViewModel.java | 130 ++++++++++++++++ .../viewmodel/ListUserReceiptViewModel.java | 25 ++- .../activity_list_prepaid_card_receipt.xml | 41 +++++ ...epaidCardReceiptDataSourceFactoryTest.java | 38 +++++ .../hyperwallet/android/ui/HyperwalletUi.java | 14 +- 17 files changed, 699 insertions(+), 18 deletions(-) create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepository.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java create mode 100644 receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java create mode 100644 receipt/src/main/res/layout/activity_list_prepaid_card_receipt.xml create mode 100644 receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactoryTest.java diff --git a/receipt/build.gradle b/receipt/build.gradle index cff209c86..48e65ce23 100644 --- a/receipt/build.gradle +++ b/receipt/build.gradle @@ -10,6 +10,8 @@ dependencies { implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion" implementation "androidx.paging:paging-runtime:$pagingRuntimeVersion" + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation "org.robolectric:robolectric:$robolectricVersion" androidTestImplementation "androidx.test:rules:$testRulesVersion" diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java new file mode 100644 index 000000000..51cfef89d --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java @@ -0,0 +1,107 @@ +package com.hyperwallet.android.ui.receipt; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +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.ui.receipt.view.ListPrepaidCardReceiptActivity.EXTRA_PREPAID_CARD_TOKEN; + +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.widget.TextView; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.espresso.IdlingRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ActivityTestRule; + +import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; +import com.hyperwallet.android.ui.receipt.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.ui.receipt.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.receipt.util.TestAuthenticationProvider; +import com.hyperwallet.android.ui.receipt.view.ListPrepaidCardReceiptActivity; + +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 ListPrepaidCardReceiptsTest { + + @ClassRule + public static HyperwalletExternalResourceManager sResourceManager = new HyperwalletExternalResourceManager(); + @Rule + public HyperwalletMockWebServer mMockWebServer = new HyperwalletMockWebServer(8080); + @Rule + public ActivityTestRule mActivityTestRule = + new ActivityTestRule(ListPrepaidCardReceiptActivity.class, true, false) { + @Override + protected Intent getActivityIntent() { + Intent intent = new Intent(ApplicationProvider.getApplicationContext(), + ListPrepaidCardReceiptActivity.class); + intent.putExtra(EXTRA_PREPAID_CARD_TOKEN, "trm-test-token-bla-bla"); + return intent; + } + }; + + @Before + public void setup() { + Hyperwallet.getInstance(new TestAuthenticationProvider()); + + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("authentication_token_response.json")).mock(); + + setLocale(Locale.US); + IdlingRegistry.getInstance().register(EspressoIdlingResource.getIdlingResource()); + } + + @After + public void unregisterIdlingResource() { + IdlingRegistry.getInstance().unregister(EspressoIdlingResource.getIdlingResource()); + } + + @Test + public void testListReceipt_userHasMultipleTransactions() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("ppc_receipt_list.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())); + } + + 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/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index 3cf88bfc1..2c573851d 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -6,11 +6,16 @@ - - + android:networkSecurityConfig="@xml/network_security_config" + tools:targetApi="n"> + + mDataSourceMutableLiveData; + private final PrepaidCardReceiptDataSource mPrepaidCardReceiptDataSource; + + PrepaidCardReceiptDataSourceFactory(@NonNull final String token) { + mPrepaidCardReceiptDataSource = new PrepaidCardReceiptDataSource(token); + mDataSourceMutableLiveData = new MutableLiveData<>(); + mDataSourceMutableLiveData.setValue(mPrepaidCardReceiptDataSource); + } + + /** + * Returns observable members of prepaid card receipt data source + */ + LiveData getPrepaidCardReceiptDataSource() { + return mDataSourceMutableLiveData; + } + + /** + * @see {@link DataSource.Factory#create()} + */ + @NonNull + @Override + public DataSource create() { + return mPrepaidCardReceiptDataSource; + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepository.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepository.java new file mode 100644 index 000000000..021cadcc7 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepository.java @@ -0,0 +1,55 @@ +/* + * 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.ui.receipt.repository; + +import androidx.lifecycle.LiveData; +import androidx.paging.PagedList; + +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.ui.common.viewmodel.Event; + +public interface PrepaidCardReceiptRepository { + + /** + * Load prepaid card receipts information, consumer can subscribe to receipts data changes events + * + * @return live data paged prepaid card receipts + */ + LiveData> loadPrepaidCardReceipts(); + + /** + * 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/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java new file mode 100644 index 000000000..43cb3e7a6 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java @@ -0,0 +1,75 @@ +package com.hyperwallet.android.ui.receipt.repository; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.paging.LivePagedListBuilder; +import androidx.paging.PagedList; + +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.ui.common.viewmodel.Event; + +public class PrepaidCardReceiptRepositoryImpl implements PrepaidCardReceiptRepository { + + private static final int PAGE_SIZE = 10; + private static final int INITIAL_LOAD_SIZE = 20; + + private final PrepaidCardReceiptDataSourceFactory mDataSourceFactory; + private final LiveData mReceiptDataSourceLiveData; + private LiveData> mErrorsLiveData; + private LiveData mIsFetchingData; + private LiveData> mReceiptsLiveData; + + public PrepaidCardReceiptRepositoryImpl(@NonNull final String token) { + mDataSourceFactory = new PrepaidCardReceiptDataSourceFactory(token); + mReceiptDataSourceLiveData = mDataSourceFactory.getPrepaidCardReceiptDataSource(); + } + + /** + * @see {@link PrepaidCardReceiptRepository#loadPrepaidCardReceipts()} + */ + @Override + public LiveData> loadPrepaidCardReceipts() { + 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 PrepaidCardReceiptRepository#isLoading()} + */ + @Override + public LiveData isLoading() { + if (mIsFetchingData == null) { + mIsFetchingData = mReceiptDataSourceLiveData.getValue().isFetchingData(); + } + return mIsFetchingData; + } + + /** + * @see {@link PrepaidCardReceiptRepository#getErrors()} + */ + @Override + public LiveData> getErrors() { + if (mErrorsLiveData == null) { + mErrorsLiveData = mReceiptDataSourceLiveData.getValue().getErrors(); + } + return mErrorsLiveData; + } + + /** + * @see {@link PrepaidCardReceiptRepository#retryLoadReceipt()} + */ + @Override + public void retryLoadReceipt() { + if (mReceiptDataSourceLiveData.getValue() != null) { + mReceiptDataSourceLiveData.getValue().retry(); + } + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java index 5d552f557..f352d843f 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java @@ -22,7 +22,7 @@ import androidx.paging.DataSource; /** - * Data source factory that uses {@link DataSource.Factory} facility + * Data source factory for User receipt data source, that uses {@link DataSource.Factory} facility */ public class UserReceiptDataSourceFactory extends DataSource.Factory { @@ -37,7 +37,7 @@ public class UserReceiptDataSourceFactory extends DataSource.Factory { } /** - * Returns observable members of receipt data source + * Returns observable members of user receipt data source */ LiveData getUserReceiptDataSource() { return mDataSourceMutableLiveData; diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepository.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepository.java index efafa90a2..7c72ab664 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepository.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepository.java @@ -29,11 +29,11 @@ public interface UserReceiptRepository { /** - * Load receipts information, consumer can subscribe to receipts data changes events + * Load user receipts information, consumer can subscribe to receipts data changes events * - * @return live data paged receipts + * @return live data paged user receipts */ - LiveData> loadReceipts(); + LiveData> loadUserReceipts(); /** * Loading indicator consumer can subscribe to loading of data events diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java index f15f9147f..b27489eaf 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java @@ -44,10 +44,10 @@ public UserReceiptRepositoryImpl() { } /** - * @see {@link UserReceiptRepository#loadReceipts()} + * @see {@link UserReceiptRepository#loadUserReceipts()} */ @Override - public LiveData> loadReceipts() { + public LiveData> loadUserReceipts() { if (mReceiptsLiveData == null) { PagedList.Config config = new PagedList.Config.Builder() .setPageSize(PAGE_SIZE) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java new file mode 100644 index 000000000..f1147575e --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java @@ -0,0 +1,143 @@ +/* + * 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.ui.receipt.view; + +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; + +import androidx.annotation.NonNull; +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.model.HyperwalletError; +import com.hyperwallet.android.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; +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.common.viewmodel.ListDetailNavigator; +import com.hyperwallet.android.ui.receipt.R; +import com.hyperwallet.android.ui.receipt.repository.PrepaidCardReceiptRepositoryImpl; +import com.hyperwallet.android.ui.receipt.viewmodel.ListPrepaidCardReceiptViewModel; +import com.hyperwallet.android.ui.receipt.viewmodel.ReceiptViewModel; + +import java.util.List; + +public class ListPrepaidCardReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback, + ListDetailNavigator> { + + public static final String EXTRA_PREPAID_CARD_TOKEN = "PREPAID_CARD_TOKEN"; + + private ReceiptViewModel mReceiptViewModel; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_list_prepaid_card_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(); + } + }); + + String token = getIntent().getStringExtra(EXTRA_PREPAID_CARD_TOKEN); + if (TextUtils.isEmpty(token)) { + throw new IllegalArgumentException("Activity " + ListPrepaidCardReceiptActivity.class.getName() + + " requires parameter: EXTRA_" + EXTRA_PREPAID_CARD_TOKEN + " value"); + } + + mReceiptViewModel = ViewModelProviders.of(this, new ListPrepaidCardReceiptViewModel + .ListPrepaidCardReceiptViewModelFactory(new PrepaidCardReceiptRepositoryImpl(token))) + .get(ReceiptViewModel.class); + + mReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { + @Override + public void onChanged(Event event) { + if (event != null && !event.isContentConsumed()) { + showErrorOnLoadReceipt(event.getContent().getErrors()); + } + } + }); + + mReceiptViewModel.getDetailNavigation().observe(this, new Observer>() { + @Override + public void onChanged(@NonNull final Event event) { + navigate(event); + } + }); + + if (savedInstanceState == null) { + initFragment(ListReceiptFragment.newInstance()); + } + } + + @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(); + } + + @Override + public void navigate(@NonNull final Event event) { + if (!event.isContentConsumed()) { + Intent intent = new Intent(this, ReceiptDetailActivity.class); + intent.putExtra(ReceiptDetailActivity.EXTRA_RECEIPT, event.getContent()); + startActivity(intent); + } + } + + private void initFragment(@NonNull final Fragment fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.add(R.id.list_receipt_fragment, fragment); + fragmentTransaction.commit(); + } + + 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/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index 51075c28d..d8e88923e 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -46,7 +46,6 @@ import com.hyperwallet.android.ui.common.util.DateUtils; import com.hyperwallet.android.ui.common.view.OneClickListener; import com.hyperwallet.android.ui.receipt.R; -import com.hyperwallet.android.ui.receipt.viewmodel.ListUserReceiptViewModel; import com.hyperwallet.android.ui.receipt.viewmodel.ReceiptViewModel; import java.text.DecimalFormat; @@ -80,7 +79,7 @@ static ListReceiptFragment newInstance() { public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReceiptViewModel = ViewModelProviders.of(requireActivity()).get( - ListUserReceiptViewModel.class); + ReceiptViewModel.class); } @Override diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java index e97acf5c9..bc66e9609 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java @@ -68,7 +68,7 @@ public void onClick(View v) { mReceiptViewModel = ViewModelProviders.of(this, new ListUserReceiptViewModel .ListReceiptViewModelFactory(new UserReceiptRepositoryImpl())) - .get(ListUserReceiptViewModel.class); + .get(ReceiptViewModel.class); mReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { @Override diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java new file mode 100644 index 000000000..3cbcef46d --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java @@ -0,0 +1,130 @@ +/* + * 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.ui.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.model.HyperwalletErrors; +import com.hyperwallet.android.model.receipt.Receipt; +import com.hyperwallet.android.ui.common.viewmodel.Event; +import com.hyperwallet.android.ui.receipt.repository.PrepaidCardReceiptRepository; + +public class ListPrepaidCardReceiptViewModel extends ReceiptViewModel { + + private MutableLiveData> mErrorEvent = new MutableLiveData<>(); + private MutableLiveData> mDetailNavigation = new MutableLiveData<>(); + private Observer> mErrorEventObserver; + private PrepaidCardReceiptRepository mPrepaidCardReceiptRepository; + + private ListPrepaidCardReceiptViewModel(@NonNull final PrepaidCardReceiptRepository receiptRepository) { + mPrepaidCardReceiptRepository = receiptRepository; + // load initial receipts + mPrepaidCardReceiptRepository.loadPrepaidCardReceipts(); + + // register one time error event observer + mErrorEventObserver = new Observer>() { + @Override + public void onChanged(Event event) { + mErrorEvent.postValue(event); + } + }; + mPrepaidCardReceiptRepository.getErrors().observeForever(mErrorEventObserver); + } + + /** + * @see {@link ReceiptViewModel#isLoadingData()} + */ + @Override + public LiveData isLoadingData() { + return mPrepaidCardReceiptRepository.isLoading(); + } + + /** + * @see {@link ReceiptViewModel#getReceiptErrors()} + */ + @Override + public LiveData> getReceiptErrors() { + return mErrorEvent; + } + + /** + * @see {@link ReceiptViewModel#getReceiptList()} + */ + @Override + public LiveData> getReceiptList() { + return mPrepaidCardReceiptRepository.loadPrepaidCardReceipts(); + } + + /** + * @see {@link ReceiptViewModel#retryLoadReceipts()} + */ + @Override + public void retryLoadReceipts() { + mPrepaidCardReceiptRepository.retryLoadReceipt(); + } + + /** + * @see {@link ReceiptViewModel#getDetailNavigation()} + */ + @Override + public LiveData> getDetailNavigation() { + return mDetailNavigation; + } + + /** + * @see {@link ReceiptViewModel#setDetailNavigation(Receipt)} + */ + @Override + public void setDetailNavigation(@NonNull Receipt receipt) { + mDetailNavigation.postValue(new Event<>(receipt)); + } + + /** + * @see {@link ViewModel#onCleared()} + */ + @Override + protected void onCleared() { + super.onCleared(); + mPrepaidCardReceiptRepository.getErrors().removeObserver(mErrorEventObserver); + mPrepaidCardReceiptRepository = null; + } + + public static class ListPrepaidCardReceiptViewModelFactory implements ViewModelProvider.Factory { + + private final PrepaidCardReceiptRepository mPrepaidCardReceiptRepository; + + public ListPrepaidCardReceiptViewModelFactory(@NonNull final PrepaidCardReceiptRepository repository) { + mPrepaidCardReceiptRepository = repository; + } + + @NonNull + @Override + public T create(@NonNull final Class modelClass) { + if (modelClass.isAssignableFrom(ListUserReceiptViewModel.class)) { + return (T) new ListPrepaidCardReceiptViewModel(mPrepaidCardReceiptRepository); + } + throw new IllegalArgumentException( + "Expecting ViewModel class: " + ListPrepaidCardReceiptViewModel.class.getName()); + } + } +} diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java index 5fefdf153..cf16664cf 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java @@ -39,7 +39,7 @@ public class ListUserReceiptViewModel extends ReceiptViewModel { private ListUserReceiptViewModel(@NonNull final UserReceiptRepository userReceiptRepository) { mUserReceiptRepository = userReceiptRepository; // load initial receipts - mUserReceiptRepository.loadReceipts(); + mUserReceiptRepository.loadUserReceipts(); // register one time error event observer mErrorEventObserver = new Observer>() { @@ -51,30 +51,51 @@ public void onChanged(Event event) { mUserReceiptRepository.getErrors().observeForever(mErrorEventObserver); } + /** + * @see {@link ReceiptViewModel#isLoadingData()} + */ public LiveData isLoadingData() { return mUserReceiptRepository.isLoading(); } + /** + * @see {@link ReceiptViewModel#getReceiptErrors()} + */ public LiveData> getReceiptErrors() { return mErrorEvent; } + /** + * @see {@link ReceiptViewModel#getReceiptList()} + */ public LiveData> getReceiptList() { - return mUserReceiptRepository.loadReceipts(); + return mUserReceiptRepository.loadUserReceipts(); } + /** + * @see {@link ReceiptViewModel#retryLoadReceipts()} + * */ public void retryLoadReceipts() { mUserReceiptRepository.retryLoadReceipt(); } + /** + * @see {@link ReceiptViewModel#getDetailNavigation()} + * */ public LiveData> getDetailNavigation() { return mDetailNavigation; } + /** + * @see {@link ReceiptViewModel#setDetailNavigation(Receipt)} + * */ public void setDetailNavigation(@NonNull final Receipt receipt) { mDetailNavigation.postValue(new Event<>(receipt)); } + /** + * @see {@link ViewModel#onCleared()} + * */ @Override protected void onCleared() { super.onCleared(); diff --git a/receipt/src/main/res/layout/activity_list_prepaid_card_receipt.xml b/receipt/src/main/res/layout/activity_list_prepaid_card_receipt.xml new file mode 100644 index 000000000..03376549f --- /dev/null +++ b/receipt/src/main/res/layout/activity_list_prepaid_card_receipt.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactoryTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactoryTest.java new file mode 100644 index 000000000..30a2e35e4 --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactoryTest.java @@ -0,0 +1,38 @@ +package com.hyperwallet.android.ui.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 PrepaidCardReceiptDataSourceFactoryTest { + + @Test + public void testGetReceiptDataSource_returnsLiveDataReceiptSource() { + // initialize + PrepaidCardReceiptDataSourceFactory dataSourceFactory = new PrepaidCardReceiptDataSourceFactory("token"); + // test + LiveData liveData = dataSourceFactory.getPrepaidCardReceiptDataSource(); + // assert + assertThat(liveData, is(notNullValue())); + } + + @Test + public void testCreate_returnsDataSource() { + // initialize + PrepaidCardReceiptDataSourceFactory dataSourceFactory = new PrepaidCardReceiptDataSourceFactory("token"); + // test + DataSource dataSource = dataSourceFactory.create(); + // assert + assertThat(dataSource, is(notNullValue())); + assertThat(dataSource, CoreMatchers.instanceOf(PrepaidCardReceiptDataSource.class)); + } +} 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 21850b5b9..21e5ac913 100644 --- a/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java +++ b/ui/src/main/java/com/hyperwallet/android/ui/HyperwalletUi.java @@ -19,6 +19,7 @@ package com.hyperwallet.android.ui; +import static com.hyperwallet.android.ui.receipt.view.ListPrepaidCardReceiptActivity.EXTRA_PREPAID_CARD_TOKEN; import static com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity.EXTRA_TRANSFER_METHOD_COUNTRY; 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; @@ -31,6 +32,7 @@ import com.hyperwallet.android.Hyperwallet; import com.hyperwallet.android.HyperwalletAuthenticationTokenProvider; +import com.hyperwallet.android.ui.receipt.view.ListPrepaidCardReceiptActivity; import com.hyperwallet.android.ui.receipt.view.ListUserReceiptActivity; import com.hyperwallet.android.ui.transfermethod.AddTransferMethodActivity; import com.hyperwallet.android.ui.transfermethod.ListTransferMethodActivity; @@ -83,10 +85,20 @@ public Intent getIntentSelectTransferMethodActivity(@NonNull final Context conte * @param context A Context of the application consuming this Intent. * @return an Intent with the data necessary to launch the {@link ListUserReceiptActivity} */ - public Intent getIntentListReceiptActivity(@NonNull final Context context) { + public Intent getIntentListUserReceiptActivity(@NonNull final Context context) { return new Intent(context, ListUserReceiptActivity.class); } + /** + * @param context A Context of the application consuming this Intent. + * @return an Intent with the data necessary to launch the {@link ListPrepaidCardReceiptActivity} + */ + public Intent getIntentListPrepaidCardReceiptActivity(@NonNull final Context context, @NonNull final String token) { + Intent intent = new Intent(context, ListPrepaidCardReceiptActivity.class); + intent.putExtra(EXTRA_PREPAID_CARD_TOKEN, token); + return intent; + } + /** * @param context A Context of the application consuming this Intent. * @param country The transfer method country code. ISO 3166-1 alpha-2 format. From 77ade14bca5f41f12c9ec6da6dc8b5fc7fd7068a Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 19 Jun 2019 15:59:47 -0700 Subject: [PATCH 29/36] fixed test --- .../receipt/ListPrepaidCardReceiptsTest.java | 2 +- .../PrepaidCardReceiptDataSourceTest.java | 4 +- .../resources/prepaid_card_receipt_list.json | 96 +++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 receipt/src/test/resources/prepaid_card_receipt_list.json diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java index 51cfef89d..b124b3f6a 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java @@ -80,7 +80,7 @@ public void unregisterIdlingResource() { @Test public void testListReceipt_userHasMultipleTransactions() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("ppc_receipt_list.json")).mock(); + .getResourceContent("prepaid_card_receipt_list.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); // run test diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java index 90a00eed5..d579b7582 100644 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java @@ -88,7 +88,7 @@ public void setUp() { @Test public void testLoadInitial_returnsReceipts() throws Exception { - String json = mExternalResourceManager.getResourceContent("ppc_receipt_list.json"); + String json = mExternalResourceManager.getResourceContent("prepaid_card_receipt_list.json"); JSONObject jsonObject = new JSONObject(json); final HyperwalletPageList response = new HyperwalletPageList<>(jsonObject, Receipt.class); @@ -245,7 +245,7 @@ public Object answer(InvocationOnMock invocation) { @Test public void testLoadAfter_returnsReceipts() throws Exception { - String json = mExternalResourceManager.getResourceContent("ppc_receipt_list.json"); + String json = mExternalResourceManager.getResourceContent("prepaid_card_receipt_list.json"); JSONObject jsonObject = new JSONObject(json); final HyperwalletPageList response = new HyperwalletPageList<>(jsonObject, Receipt.class); diff --git a/receipt/src/test/resources/prepaid_card_receipt_list.json b/receipt/src/test/resources/prepaid_card_receipt_list.json new file mode 100644 index 000000000..95715bb7a --- /dev/null +++ b/receipt/src/test/resources/prepaid_card_receipt_list.json @@ -0,0 +1,96 @@ +{ + "data": [ + { + "journalId": "FISVL_5240220", + "type": "DEPOSIT", + "createdOn": "2019-06-06T22:48:41", + "entry": "CREDIT", + "destinationToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "10.00", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + }, + { + "journalId": "FISVL_5240221", + "type": "DEPOSIT", + "createdOn": "2019-06-06T22:48:51", + "entry": "CREDIT", + "destinationToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "5.00", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + }, + { + "journalId": "FISA_5240222", + "type": "ADJUSTMENT", + "createdOn": "2019-06-06T22:49:17", + "entry": "DEBIT", + "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "8.90", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + }, + { + "journalId": "FISA_5240223", + "type": "ADJUSTMENT", + "createdOn": "2019-03-31T23:55:17", + "entry": "DEBIT", + "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "7.90", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + }, + { + "journalId": "FISA_5240224", + "type": "ADJUSTMENT", + "createdOn": "2019-02-28T23:55:17", + "entry": "CREDIT", + "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "6.90", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + }, + { + "journalId": "FISA_5240225", + "type": "ADJUSTMENT", + "createdOn": "2019-02-23T23:55:17", + "entry": "CREDIT", + "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "3.90", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + }, + { + "journalId": "FISA_5240226", + "type": "ADJUSTMENT", + "createdOn": "2019-02-21T23:55:17", + "entry": "CREDIT", + "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "9.92", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-e17ae43b-284d-4198-9585-f417943c624f/prepaid-cards/trm-2e02da75-a36c-4723-b613-0b64e6f582d9/receipts" + } + ] +} \ No newline at end of file From 21175ff5f7d25ec3736f5361ebe1f08a5a51f7bf Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Fri, 21 Jun 2019 13:02:19 -0700 Subject: [PATCH 30/36] removed extra import --- receipt/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/receipt/build.gradle b/receipt/build.gradle index 48e65ce23..cff209c86 100644 --- a/receipt/build.gradle +++ b/receipt/build.gradle @@ -10,8 +10,6 @@ dependencies { implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion" implementation "androidx.paging:paging-runtime:$pagingRuntimeVersion" - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation "org.robolectric:robolectric:$robolectricVersion" androidTestImplementation "androidx.test:rules:$testRulesVersion" From 7cf603c11e58edb1788a96e2b2ba42fc5d3c2a5d Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Mon, 24 Jun 2019 11:32:44 -0700 Subject: [PATCH 31/36] local review --- .../PrepaidCardReceiptDataSource.java | 3 ++- .../PrepaidCardReceiptDataSourceFactory.java | 1 + .../repository/UserReceiptDataSource.java | 6 ++--- .../view/ListPrepaidCardReceiptActivity.java | 2 +- .../ui/receipt/view/ListReceiptFragment.java | 5 ++-- .../main/res/layout/fragment_list_receipt.xml | 25 +++++++++++++++++++ 6 files changed, 34 insertions(+), 8 deletions(-) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java index 16bddfc64..e3abd333d 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java @@ -67,7 +67,7 @@ public class PrepaidCardReceiptDataSource extends PageKeyedDataSource params, public void loadAfter(@NonNull final LoadParams params, @NonNull final LoadCallback callback) { mLoadAfterCallback = callback; mLoadAfterParams = params; + mIsFetchingData.postValue(Boolean.TRUE); ReceiptQueryParam queryParam = new ReceiptQueryParam.Builder() .createdAfter(params.key) diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java index 38288481d..d1b821a06 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java @@ -30,6 +30,7 @@ public class PrepaidCardReceiptDataSourceFactory extends DataSource.Factory { private final PrepaidCardReceiptDataSource mPrepaidCardReceiptDataSource; PrepaidCardReceiptDataSourceFactory(@NonNull final String token) { + super(); mPrepaidCardReceiptDataSource = new PrepaidCardReceiptDataSource(token); mDataSourceMutableLiveData = new MutableLiveData<>(); mDataSourceMutableLiveData.setValue(mPrepaidCardReceiptDataSource); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java index 766dc4c1e..a2734f99d 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java @@ -111,15 +111,15 @@ public Handler getHandler() { * @see {@link PageKeyedDataSource#loadBefore(LoadParams, LoadCallback)} */ @Override - public void loadBefore(@NonNull LoadParams params, - @NonNull LoadCallback callback) { + public void loadBefore(@NonNull final LoadParams params, + @NonNull final LoadCallback callback) { } /** * @see {@link PageKeyedDataSource#loadAfter(LoadParams, LoadCallback)} * */ @Override - public void loadAfter(@NonNull LoadParams params, + public void loadAfter(@NonNull final LoadParams params, final @NonNull LoadCallback callback) { mLoadInitialCallback = null; mLoadInitialParams = null; diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java index f1147575e..b774436d4 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListPrepaidCardReceiptActivity.java @@ -71,7 +71,7 @@ public void onClick(View v) { String token = getIntent().getStringExtra(EXTRA_PREPAID_CARD_TOKEN); if (TextUtils.isEmpty(token)) { throw new IllegalArgumentException("Activity " + ListPrepaidCardReceiptActivity.class.getName() - + " requires parameter: EXTRA_" + EXTRA_PREPAID_CARD_TOKEN + " value"); + + " requires parameter: " + EXTRA_PREPAID_CARD_TOKEN + " value"); } mReceiptViewModel = ViewModelProviders.of(this, new ListPrepaidCardReceiptViewModel diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index d8e88923e..ffcbf75ae 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -217,7 +217,7 @@ public void onOneClick(View v) { } }); - // By design decision from here under, this code is also repeated in ReceiptDetailFragment + // By design decision from hereon, this code is also repeated in ReceiptDetailFragment TextView transactionTypeIcon = itemView.findViewById(R.id.transaction_type_icon); TextView transactionTitle = itemView.findViewById(R.id.transaction_title); TextView transactionDate = itemView.findViewById(R.id.transaction_date); @@ -274,8 +274,7 @@ class ReceiptViewHolderWithHeader extends ReceiptViewHolder { private final TextView mTransactionHeaderText; - ReceiptViewHolderWithHeader(@NonNull final ReceiptViewModel receiptViewModel, - @NonNull final View item) { + ReceiptViewHolderWithHeader(@NonNull final ReceiptViewModel receiptViewModel, @NonNull final View item) { super(receiptViewModel, item); mTransactionHeaderText = item.findViewById(R.id.item_date_header_title); } diff --git a/receipt/src/main/res/layout/fragment_list_receipt.xml b/receipt/src/main/res/layout/fragment_list_receipt.xml index 52e9725db..f6463cf45 100644 --- a/receipt/src/main/res/layout/fragment_list_receipt.xml +++ b/receipt/src/main/res/layout/fragment_list_receipt.xml @@ -23,4 +23,29 @@ android:indeterminate="true" android:theme="@style/Widget.Hyperwallet.ProgressBar.Receipts"/> + + + + + + + + \ No newline at end of file From d4c97ea4ea8970db81751a1f3feece2110228255 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Tue, 25 Jun 2019 13:48:47 -0700 Subject: [PATCH 32/36] change data --- .../android/ui/receipt/ListPrepaidCardReceiptsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java index b124b3f6a..e9076ea1e 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java @@ -56,7 +56,7 @@ public class ListPrepaidCardReceiptsTest { protected Intent getActivityIntent() { Intent intent = new Intent(ApplicationProvider.getApplicationContext(), ListPrepaidCardReceiptActivity.class); - intent.putExtra(EXTRA_PREPAID_CARD_TOKEN, "trm-test-token-bla-bla"); + intent.putExtra(EXTRA_PREPAID_CARD_TOKEN, "trm-test-token"); return intent; } }; From e47433caca6b43dc744c5fc696ab505e3d5b5069 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Wed, 26 Jun 2019 08:47:24 -0700 Subject: [PATCH 33/36] fix javadocs --- .../android/ui/receipt/ListUserReceiptsTest.java | 2 +- .../repository/PrepaidCardReceiptDataSource.java | 14 +++----------- .../PrepaidCardReceiptDataSourceFactory.java | 2 +- .../PrepaidCardReceiptRepositoryImpl.java | 8 ++++---- .../receipt/repository/UserReceiptDataSource.java | 6 +++--- .../repository/UserReceiptDataSourceFactory.java | 2 +- .../repository/UserReceiptRepositoryImpl.java | 8 ++++---- .../ui/receipt/view/ListReceiptFragment.java | 2 +- .../ui/receipt/view/ReceiptDetailFragment.java | 4 ++-- .../viewmodel/ListPrepaidCardReceiptViewModel.java | 14 +++++++------- .../viewmodel/ListUserReceiptViewModel.java | 14 +++++++------- .../PrepaidCardReceiptDataSourceTest.java | 4 ++-- 12 files changed, 36 insertions(+), 44 deletions(-) diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java index 5ff5bf299..f510302c4 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java @@ -366,7 +366,7 @@ public void testListReceipt_clickTransactionDisplaysDetailsWithoutFees() { } @Test - public void testListReceipt_verifyTransactionsLoadedUponScrolling() throws InterruptedException { + public void testListReceipt_verifyTransactionsLoadedUponScrolling() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_list_paged_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java index e3abd333d..352ae0913 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java @@ -20,7 +20,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.paging.PageKeyedDataSource; @@ -55,13 +54,6 @@ public class PrepaidCardReceiptDataSource extends PageKeyedDataSource mLoadInitialCallback; private PageKeyedDataSource.LoadInitialParams mLoadInitialParams; - @VisibleForTesting - PrepaidCardReceiptDataSource() { - mCalendarYearBeforeNow = Calendar.getInstance(); - mCalendarYearBeforeNow.add(Calendar.YEAR, YEAR_BEFORE_NOW); - mToken = "trm-test-token"; - } - /** * Initialize Prepaid card data source * @@ -74,7 +66,7 @@ public class PrepaidCardReceiptDataSource extends PageKeyedDataSource params, @@ -117,7 +109,7 @@ public Handler getHandler() { } /** - * @see {@link PageKeyedDataSource#loadBefore(LoadParams, LoadCallback)} + * @see PageKeyedDataSource#loadBefore(LoadParams, LoadCallback) */ @Override public void loadBefore(@NonNull final LoadParams params, @@ -125,7 +117,7 @@ public void loadBefore(@NonNull final LoadParams params, } /** - * @see {@link PageKeyedDataSource#loadAfter(LoadParams, LoadCallback)} + * @see PageKeyedDataSource#loadAfter(LoadParams, LoadCallback) */ @Override public void loadAfter(@NonNull final LoadParams params, @NonNull final LoadCallback callback) { diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java index d1b821a06..71edf3f7a 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java @@ -44,7 +44,7 @@ LiveData getPrepaidCardReceiptDataSource() { } /** - * @see {@link DataSource.Factory#create()} + * @see DataSource.Factory#create() */ @NonNull @Override diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java index 43cb3e7a6..4b5fed137 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptRepositoryImpl.java @@ -26,7 +26,7 @@ public PrepaidCardReceiptRepositoryImpl(@NonNull final String token) { } /** - * @see {@link PrepaidCardReceiptRepository#loadPrepaidCardReceipts()} + * @see PrepaidCardReceiptRepository#loadPrepaidCardReceipts() */ @Override public LiveData> loadPrepaidCardReceipts() { @@ -42,7 +42,7 @@ public LiveData> loadPrepaidCardReceipts() { } /** - * @see {@link PrepaidCardReceiptRepository#isLoading()} + * @see PrepaidCardReceiptRepository#isLoading() */ @Override public LiveData isLoading() { @@ -53,7 +53,7 @@ public LiveData isLoading() { } /** - * @see {@link PrepaidCardReceiptRepository#getErrors()} + * @see PrepaidCardReceiptRepository#getErrors() */ @Override public LiveData> getErrors() { @@ -64,7 +64,7 @@ public LiveData> getErrors() { } /** - * @see {@link PrepaidCardReceiptRepository#retryLoadReceipt()} + * @see PrepaidCardReceiptRepository#retryLoadReceipt() */ @Override public void retryLoadReceipt() { diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java index a2734f99d..28e8ef727 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java @@ -58,7 +58,7 @@ public class UserReceiptDataSource extends PageKeyedDataSource } /** - * @see {@link PageKeyedDataSource#loadInitial(LoadInitialParams, LoadInitialCallback)} + * @see PageKeyedDataSource#loadInitial(LoadInitialParams, LoadInitialCallback) */ @Override public void loadInitial(@NonNull final LoadInitialParams params, @@ -108,7 +108,7 @@ public Handler getHandler() { /** * Unused in this case * - * @see {@link PageKeyedDataSource#loadBefore(LoadParams, LoadCallback)} + * @see PageKeyedDataSource#loadBefore(LoadParams, LoadCallback) */ @Override public void loadBefore(@NonNull final LoadParams params, @@ -116,7 +116,7 @@ public void loadBefore(@NonNull final LoadParams params, } /** - * @see {@link PageKeyedDataSource#loadAfter(LoadParams, LoadCallback)} + * @see PageKeyedDataSource#loadAfter(LoadParams, LoadCallback) * */ @Override public void loadAfter(@NonNull final LoadParams params, diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java index f352d843f..e974a0c05 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java @@ -44,7 +44,7 @@ LiveData getUserReceiptDataSource() { } /** - * @see {@link DataSource.Factory#create()} + * @see DataSource.Factory#create() */ @NonNull @Override diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java index b27489eaf..07a8fbdb9 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java @@ -44,7 +44,7 @@ public UserReceiptRepositoryImpl() { } /** - * @see {@link UserReceiptRepository#loadUserReceipts()} + * @see UserReceiptRepository#loadUserReceipts() */ @Override public LiveData> loadUserReceipts() { @@ -60,7 +60,7 @@ public LiveData> loadUserReceipts() { } /** - * @see {@link UserReceiptRepository#isLoading()} + * @see UserReceiptRepository#isLoading() */ @Override public LiveData isLoading() { @@ -71,7 +71,7 @@ public LiveData isLoading() { } /** - * @see {@link UserReceiptRepository#getErrors()} + * @see UserReceiptRepository#getErrors() * */ @Override public LiveData> getErrors() { @@ -82,7 +82,7 @@ public LiveData> getErrors() { } /** - * @see {@link UserReceiptRepository#retryLoadReceipt()} + * @see UserReceiptRepository#retryLoadReceipt() * */ @Override public void retryLoadReceipt() { diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java index ffcbf75ae..64f3611c2 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListReceiptFragment.java @@ -64,7 +64,7 @@ public class ListReceiptFragment extends Fragment { /** * Please don't use this constructor this is reserved for Android Core Framework * - * @see {@link ListReceiptFragment#newInstance()} instead. + * @see #newInstance() */ public ListReceiptFragment() { setRetainInstance(true); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java index 8e8f99dec..7c9a349b1 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ReceiptDetailFragment.java @@ -52,8 +52,8 @@ public class ReceiptDetailFragment extends Fragment { - static final String AMOUNT_FORMAT = "###0.00"; - static final String DETAIL_TIMEZONE = "zzz"; + private static final String AMOUNT_FORMAT = "###0.00"; + private static final String DETAIL_TIMEZONE = "zzz"; private ReceiptDetailViewModel mReceiptDetailViewModel; diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java index 3cbcef46d..73f697bca 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListPrepaidCardReceiptViewModel.java @@ -52,7 +52,7 @@ public void onChanged(Event event) { } /** - * @see {@link ReceiptViewModel#isLoadingData()} + * @see ReceiptViewModel#isLoadingData() */ @Override public LiveData isLoadingData() { @@ -60,7 +60,7 @@ public LiveData isLoadingData() { } /** - * @see {@link ReceiptViewModel#getReceiptErrors()} + * @see ReceiptViewModel#getReceiptErrors() */ @Override public LiveData> getReceiptErrors() { @@ -68,7 +68,7 @@ public LiveData> getReceiptErrors() { } /** - * @see {@link ReceiptViewModel#getReceiptList()} + * @see ReceiptViewModel#getReceiptList() */ @Override public LiveData> getReceiptList() { @@ -76,7 +76,7 @@ public LiveData> getReceiptList() { } /** - * @see {@link ReceiptViewModel#retryLoadReceipts()} + * @see ReceiptViewModel#retryLoadReceipts() */ @Override public void retryLoadReceipts() { @@ -84,7 +84,7 @@ public void retryLoadReceipts() { } /** - * @see {@link ReceiptViewModel#getDetailNavigation()} + * @see ReceiptViewModel#getDetailNavigation() */ @Override public LiveData> getDetailNavigation() { @@ -92,7 +92,7 @@ public LiveData> getDetailNavigation() { } /** - * @see {@link ReceiptViewModel#setDetailNavigation(Receipt)} + * @see ReceiptViewModel#setDetailNavigation(Receipt) */ @Override public void setDetailNavigation(@NonNull Receipt receipt) { @@ -100,7 +100,7 @@ public void setDetailNavigation(@NonNull Receipt receipt) { } /** - * @see {@link ViewModel#onCleared()} + * @see ViewModel#onCleared() */ @Override protected void onCleared() { diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java index cf16664cf..9b9b63b2c 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java @@ -52,49 +52,49 @@ public void onChanged(Event event) { } /** - * @see {@link ReceiptViewModel#isLoadingData()} + * @see ReceiptViewModel#isLoadingData() */ public LiveData isLoadingData() { return mUserReceiptRepository.isLoading(); } /** - * @see {@link ReceiptViewModel#getReceiptErrors()} + * @see ReceiptViewModel#getReceiptErrors() */ public LiveData> getReceiptErrors() { return mErrorEvent; } /** - * @see {@link ReceiptViewModel#getReceiptList()} + * @see ReceiptViewModel#getReceiptList() */ public LiveData> getReceiptList() { return mUserReceiptRepository.loadUserReceipts(); } /** - * @see {@link ReceiptViewModel#retryLoadReceipts()} + * @see ReceiptViewModel#retryLoadReceipts() * */ public void retryLoadReceipts() { mUserReceiptRepository.retryLoadReceipt(); } /** - * @see {@link ReceiptViewModel#getDetailNavigation()} + * @see ReceiptViewModel#getDetailNavigation() * */ public LiveData> getDetailNavigation() { return mDetailNavigation; } /** - * @see {@link ReceiptViewModel#setDetailNavigation(Receipt)} + * @see ReceiptViewModel#setDetailNavigation(Receipt) * */ public void setDetailNavigation(@NonNull final Receipt receipt) { mDetailNavigation.postValue(new Event<>(receipt)); } /** - * @see {@link ViewModel#onCleared()} + * @see ViewModel#onCleared() * */ @Override protected void onCleared() { diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java index d579b7582..f703e7810 100644 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -39,7 +40,6 @@ 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; @@ -77,11 +77,11 @@ public class PrepaidCardReceiptDataSourceTest { @Captor private ArgumentCaptor mNextCaptor; - @Spy private PrepaidCardReceiptDataSource mPrepaidCardReceiptDataSource; @Before public void setUp() { + mPrepaidCardReceiptDataSource = spy(new PrepaidCardReceiptDataSource("test-token")); doReturn(mHyperwallet).when(mPrepaidCardReceiptDataSource).getHyperwallet(); } From 73fd5004c603d660eb8c60480159323de70a8db8 Mon Sep 17 00:00:00 2001 From: Peter Olamit Date: Thu, 27 Jun 2019 11:43:34 -0700 Subject: [PATCH 34/36] removed unused exception in test --- .../android/ui/transfermethod/ListTransferMethodTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodTest.java b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodTest.java index fc567b50e..01e3e1d29 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/ui/transfermethod/ListTransferMethodTest.java @@ -413,7 +413,7 @@ public void onReceive(Context context, Intent intent) { } @Test - public void testListTransferMethod_removeBankAccountClickCancel() throws InterruptedException { + public void testListTransferMethod_removeBankAccountClickCancel() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("transfer_method_list_response.json")).mock(); From 9383ef81e3f98698dad2bf76271164241b019972 Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Tue, 2 Jul 2019 16:46:32 -0700 Subject: [PATCH 35/36] Implement UI tests for ppc receipts --- .../receipt/ListPrepaidCardReceiptsTest.java | 380 +++++++++++++++++- .../ui/receipt/ListUserReceiptsTest.java | 10 +- .../PrepaidCardReceiptDataSource.java | 7 + .../PrepaidCardReceiptDataSourceTest.java | 4 +- .../prepaid_card_receipt_credit_response.json | 24 ++ .../prepaid_card_receipt_debit_response.json | 24 ++ ...> prepaid_card_receipt_list_response.json} | 15 +- ...id_card_receipt_unknown_type_response.json | 24 ++ 8 files changed, 475 insertions(+), 13 deletions(-) create mode 100644 receipt/src/test/resources/prepaid_card_receipt_credit_response.json create mode 100644 receipt/src/test/resources/prepaid_card_receipt_debit_response.json rename receipt/src/test/resources/{prepaid_card_receipt_list.json => prepaid_card_receipt_list_response.json} (83%) create mode 100644 receipt/src/test/resources/prepaid_card_receipt_unknown_type_response.json diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java index e9076ea1e..20802be1c 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListPrepaidCardReceiptsTest.java @@ -1,8 +1,19 @@ package com.hyperwallet.android.ui.receipt; +import static android.text.format.DateUtils.FORMAT_ABBREV_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.text.format.DateUtils.FORMAT_SHOW_TIME; +import static android.text.format.DateUtils.FORMAT_SHOW_WEEKDAY; +import static android.text.format.DateUtils.FORMAT_SHOW_YEAR; +import static android.text.format.DateUtils.formatDateTime; + import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; 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.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withText; @@ -13,6 +24,7 @@ import static java.net.HttpURLConnection.HTTP_NO_CONTENT; import static java.net.HttpURLConnection.HTTP_OK; +import static com.hyperwallet.android.ui.receipt.util.EspressoUtils.atPosition; import static com.hyperwallet.android.ui.receipt.view.ListPrepaidCardReceiptActivity.EXTRA_PREPAID_CARD_TOKEN; import android.content.Context; @@ -23,13 +35,17 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.espresso.IdlingRegistry; +import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.ui.common.util.DateUtils; import com.hyperwallet.android.ui.common.util.EspressoIdlingResource; import com.hyperwallet.android.ui.receipt.rule.HyperwalletExternalResourceManager; import com.hyperwallet.android.ui.receipt.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.receipt.util.RecyclerViewCountAssertion; import com.hyperwallet.android.ui.receipt.util.TestAuthenticationProvider; import com.hyperwallet.android.ui.receipt.view.ListPrepaidCardReceiptActivity; @@ -40,7 +56,11 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Date; import java.util.Locale; +import java.util.concurrent.TimeUnit; + +import okhttp3.mockwebserver.MockResponse; @RunWith(AndroidJUnit4.class) public class ListPrepaidCardReceiptsTest { @@ -78,18 +98,374 @@ public void unregisterIdlingResource() { } @Test - public void testListReceipt_userHasMultipleTransactions() { + public void testListPrepaidCardReceipt_userHasMultipleTransactions() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("prepaid_card_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(R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.prepaid_card_sale))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("- 10.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 6, 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(R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText(R.string.deposit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("+ 5.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("June 6, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, + hasDescendant(withText(R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("- 8.90"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("June 1, 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("March 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, + hasDescendant(withText(R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("- 7.90"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("March 31, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(4, + hasDescendant(withText(R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(4, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(4, hasDescendant(withText("+ 6.90"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(4, hasDescendant(withText("February 28, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(4, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(5, + hasDescendant(withText(R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(5, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(5, hasDescendant(withText("+ 3.90"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(5, hasDescendant(withText("February 23, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(5, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(6, + hasDescendant(withText(R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(6, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(6, hasDescendant(withText("+ 9.92"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(6, hasDescendant(withText("February 21, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(6, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(7)); + } + + @Test + public void testListPrepaidCardReceipt_userHasCreditTransaction() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("prepaid_card_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.ui.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.deposit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("+ 15.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 6, 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 testListPrepaidCardReceipt_userHasDebitTransaction() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("prepaid_card_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("June 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("- 8.90"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 1, 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 testListPrepaidCardReceipt_userHasUnknownTransactionType() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("prepaid_card_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.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( + matches(atPosition(0, hasDescendant(withText("+ 15.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 6, 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 testListPrepaidCardReceipt_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 testListPrepaidCardReceipt_checkDateTextOnLocaleChange() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("prepaid_card_receipt_list.json")).mock(); + .getResourceContent("prepaid_card_receipt_debit_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + setLocale(Locale.GERMAN); // run test mActivityTestRule.launchActivity(null); + // assert + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("Juni 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("- 8,90"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("1. Juni 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 testListPrepaidCardReceipt_displaysNetworkErrorDialogOnConnectionTimeout() { + mMockWebServer.getServer().enqueue(new MockResponse().setResponseCode(HTTP_OK).setBody(sResourceManager + .getResourceContent("prepaid_card_receipt_debit_response.json")).throttleBody(512, 10, + TimeUnit.SECONDS)); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("prepaid_card_receipt_debit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + mActivityTestRule.launchActivity(null); + + // assert error dialog information exist in portrait mode + onView(withText(R.string.error_dialog_connectivity_title)).check(matches(isDisplayed())); + onView(withText(R.string.io_exception)).check(matches(isDisplayed())); + onView(withId(android.R.id.button1)).check(matches(withText(R.string.try_again_button_label))); + onView(withId(android.R.id.button2)).check(matches(withText(R.string.cancel_button_label))); + + // retry button clicked + onView(withId(android.R.id.button1)).perform(click()); + onView(withText(R.string.error_dialog_connectivity_title)).check(doesNotExist()); // 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.ui.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.adjustment))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("- 8.90"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 1, 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 testListPrepaidCardReceipt_clickTransactionDisplaysDetails() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("prepaid_card_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)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); + + onView(withId(R.id.transaction_header_text)).check(matches(withText(R.string.transaction_header_text))); + onView(withId(R.id.transaction_type_icon)).check(matches(withText(R.string.debit))); + onView(withId(R.id.transaction_title)).check(matches(withText(R.string.prepaid_card_sale))); + onView(withId(R.id.transaction_amount)).check(matches(withText("- 10.00"))); + onView(withId(R.id.transaction_currency)).check(matches(withText("USD"))); + onView(withId(R.id.transaction_date)).check(matches(withText("June 6, 2019"))); + + onView(withId(R.id.receipt_details_header_label)).check(matches(withText(R.string.receipt_header_label))); + onView(withId(R.id.receipt_id_label)).check(matches(withText(R.string.journalId))); + onView(withId(R.id.receipt_id_value)).check(matches(withText("FISVL_5240220"))); + onView(withId(R.id.date_label)).check(matches(withText(R.string.createdOn))); + + Date date = DateUtils.fromDateTimeString("2019-06-06T22:48:41"); + String timezone = DateUtils.toDateFormat(date, "zzz"); + String text = mActivityTestRule.getActivity().getApplicationContext().getString( + R.string.concat_string_view_format, + formatDateTime(mActivityTestRule.getActivity().getApplicationContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_YEAR + | FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY), timezone); + onView(withId(R.id.date_value)).check(matches(withText(text))); + + onView(withId(R.id.client_id_label)).check(matches(withText(R.string.clientPaymentId))); + onView(withId(R.id.client_id_value)).check(matches(withText("AOxXefx9"))); + onView(withId(R.id.charity_label)).check(matches(withText(R.string.charityName))); + onView(withId(R.id.charity_value)).check(matches(withText("Sample Charity"))); + onView(withId(R.id.check_number_label)).check(matches(withText(R.string.checkNumber))); + onView(withId(R.id.check_number_value)).check(matches(withText("Sample Check Number"))); + onView(withId(R.id.website_label)).check(matches(withText(R.string.website))); + onView(withId(R.id.website_value)).check(matches(withText("https://api.sandbox.hyperwallet.com"))); + onView(withText("A Person")).check(doesNotExist()); + + onView(withId(R.id.receipt_notes_header_label)).check(matches(withText(R.string.notes))); + onView(withId(R.id.notes_value)).check( + matches(withText("Sample prepaid card payment for the period of June 15th, 2019 to July 23, 2019"))); + + onView(withId(R.id.details_header_text)).check(matches(withText(R.string.fee_details_header_text))); + onView(withId(R.id.details_amount_label)).check(matches(withText(R.string.details_amount_label))); + onView(withId(R.id.details_amount_value)).check(matches(withText("10.00 USD"))); + onView(withId(R.id.details_fee_label)).check(matches(withText(R.string.fee_label))); + onView(withId(R.id.details_fee_value)).check(matches(withText("3.00 USD"))); + onView(withId(R.id.details_transfer_amount_label)).check(matches(withText(R.string.transfer_amount_label))); + onView(withId(R.id.details_transfer_amount_value)).check(matches(withText("7.00 USD"))); + } + + @Test + public void testListPrepaidCardReceipt_clickTransactionDisplaysDetailsWithoutFees() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("prepaid_card_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)).perform(RecyclerViewActions.actionOnItemAtPosition(1, click())); + + onView(withId(R.id.transaction_header_text)).check(matches(withText(R.string.transaction_header_text))); + onView(withId(R.id.transaction_type_icon)).check(matches(withText(R.string.credit))); + onView(withId(R.id.transaction_title)).check(matches(withText(R.string.deposit))); + onView(withId(R.id.transaction_amount)).check(matches(withText("+ 5.00"))); + onView(withId(R.id.transaction_currency)).check(matches(withText("USD"))); + onView(withId(R.id.transaction_date)).check(matches(withText("June 6, 2019"))); + + onView(withId(R.id.receipt_details_header_label)).check(matches(withText(R.string.receipt_header_label))); + onView(withId(R.id.receipt_id_label)).check(matches(withText(R.string.journalId))); + onView(withId(R.id.receipt_id_value)).check(matches(withText("FISVL_5240221"))); + onView(withId(R.id.date_label)).check(matches(withText(R.string.createdOn))); + + Date date = DateUtils.fromDateTimeString("2019-06-06T22:48:51"); + String timezone = DateUtils.toDateFormat(date, "zzz"); + String text = mActivityTestRule.getActivity().getApplicationContext().getString( + R.string.concat_string_view_format, + formatDateTime(mActivityTestRule.getActivity().getApplicationContext(), date.getTime(), + FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_YEAR + | FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY), timezone); + onView(withId(R.id.date_value)).check(matches(withText(text))); + + onView(withId(R.id.client_id_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.client_id_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.charity_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.charity_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.check_number_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.check_number_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.website_label)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.website_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + + onView(withId(R.id.receipt_notes_information)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.receipt_notes_header_label)).check( + matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(R.id.notes_value)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); } private void setLocale(Locale locale) { diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java index f510302c4..0bb97d2ff 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/ui/receipt/ListUserReceiptsTest.java @@ -110,7 +110,7 @@ public void testListReceipt_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check( - matches(atPosition(0, hasDescendant(withText("Payment"))))); + matches(atPosition(0, hasDescendant(withText(R.string.payment))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(0, hasDescendant(withText("+ 20.00"))))); onView(withId(R.id.list_receipts)).check( @@ -120,7 +120,7 @@ public void testListReceipt_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check( - matches(atPosition(1, hasDescendant(withText("Payment"))))); + matches(atPosition(1, hasDescendant(withText(R.string.payment))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(1, hasDescendant(withText("+ 25.00"))))); onView(withId(R.id.list_receipts)).check( @@ -130,7 +130,7 @@ public void testListReceipt_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)).check(matches(atPosition(2, 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"))))); + matches(atPosition(2, hasDescendant(withText(R.string.card_activation_fee))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(2, hasDescendant(withText("- 1.95"))))); onView(withId(R.id.list_receipts)).check( @@ -142,7 +142,7 @@ public void testListReceipt_userHasMultipleTransactions() { onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText(com.hyperwallet.android.ui.receipt.R.string.debit))))); onView(withId(R.id.list_receipts)).check( - matches(atPosition(3, hasDescendant(withText("Card Load"))))); + matches(atPosition(3, hasDescendant(withText(R.string.transfer_to_prepaid_card))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(3, hasDescendant(withText("- 18.05"))))); onView(withId(R.id.list_receipts)).check( @@ -417,7 +417,7 @@ public void testListReceipt_checkDateTextOnLocaleChange() { @Test public void testListReceipt_displaysNetworkErrorDialogOnConnectionTimeout() { mMockWebServer.getServer().enqueue(new MockResponse().setResponseCode(HTTP_OK).setBody(sResourceManager - .getResourceContent("receipt_debit_response.json")).throttleBody(512, 15, TimeUnit.SECONDS)); + .getResourceContent("receipt_debit_response.json")).throttleBody(512, 10, TimeUnit.SECONDS)); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_debit_response.json")).mock(); mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java index 352ae0913..7f4ca4ca4 100644 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java @@ -31,6 +31,7 @@ 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.util.EspressoIdlingResource; import com.hyperwallet.android.ui.common.viewmodel.Event; import com.hyperwallet.android.util.DateUtil; @@ -79,6 +80,7 @@ public void loadInitial(@NonNull final LoadInitialParams params, .createdAfter(mCalendarYearBeforeNow.getTime()) .sortByCreatedOnDesc().build(); + EspressoIdlingResource.increment(); getHyperwallet().listPrepaidCardReceipts(mToken, queryParam, new HyperwalletListener>() { @Override @@ -93,12 +95,14 @@ public void onSuccess(@Nullable HyperwalletPageList result) { // reset mLoadInitialCallback = null; mLoadInitialParams = null; + EspressoIdlingResource.decrement(); } @Override public void onFailure(HyperwalletException exception) { mIsFetchingData.postValue(Boolean.FALSE); mErrors.postValue(new Event<>(exception.getHyperwalletErrors())); + EspressoIdlingResource.decrement(); } @Override @@ -130,6 +134,7 @@ public void loadAfter(@NonNull final LoadParams params, @NonNull final Loa .limit(params.requestedLoadSize) .sortByCreatedOnDesc().build(); + EspressoIdlingResource.increment(); getHyperwallet().listPrepaidCardReceipts(mToken, queryParam, new HyperwalletListener>() { @Override @@ -144,12 +149,14 @@ public void onSuccess(@Nullable HyperwalletPageList result) { // reset mLoadAfterCallback = null; mLoadAfterParams = null; + EspressoIdlingResource.decrement(); } @Override public void onFailure(HyperwalletException exception) { mIsFetchingData.postValue(Boolean.FALSE); mErrors.postValue(new Event<>(exception.getHyperwalletErrors())); + EspressoIdlingResource.decrement(); } @Override diff --git a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java index f703e7810..8c651ef4b 100644 --- a/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceTest.java @@ -88,7 +88,7 @@ public void setUp() { @Test public void testLoadInitial_returnsReceipts() throws Exception { - String json = mExternalResourceManager.getResourceContent("prepaid_card_receipt_list.json"); + String json = mExternalResourceManager.getResourceContent("prepaid_card_receipt_list_response.json"); JSONObject jsonObject = new JSONObject(json); final HyperwalletPageList response = new HyperwalletPageList<>(jsonObject, Receipt.class); @@ -245,7 +245,7 @@ public Object answer(InvocationOnMock invocation) { @Test public void testLoadAfter_returnsReceipts() throws Exception { - String json = mExternalResourceManager.getResourceContent("prepaid_card_receipt_list.json"); + String json = mExternalResourceManager.getResourceContent("prepaid_card_receipt_list_response.json"); JSONObject jsonObject = new JSONObject(json); final HyperwalletPageList response = new HyperwalletPageList<>(jsonObject, Receipt.class); diff --git a/receipt/src/test/resources/prepaid_card_receipt_credit_response.json b/receipt/src/test/resources/prepaid_card_receipt_credit_response.json new file mode 100644 index 000000000..152d482ba --- /dev/null +++ b/receipt/src/test/resources/prepaid_card_receipt_credit_response.json @@ -0,0 +1,24 @@ +{ + "data": [ + { + "journalId": "FISVL_5240220", + "type": "DEPOSIT", + "createdOn": "2019-06-06T22:48:41", + "entry": "CREDIT", + "destinationToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "15.00", + "currency": "CAD", + "details": { + "cardNumber": "************0673" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-e17ae43b-284d-4198-9585-f417943c624f/prepaid-cards/trm-2e02da75-a36c-4723-b613-0b64e6f582d9/receipts" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/prepaid_card_receipt_debit_response.json b/receipt/src/test/resources/prepaid_card_receipt_debit_response.json new file mode 100644 index 000000000..d26f5276c --- /dev/null +++ b/receipt/src/test/resources/prepaid_card_receipt_debit_response.json @@ -0,0 +1,24 @@ +{ + "data": [ + { + "journalId": "FISA_5240222", + "type": "ADJUSTMENT", + "createdOn": "2019-06-01T22:49:17", + "entry": "DEBIT", + "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "8.90", + "currency": "USD", + "details": { + "cardNumber": "************0673" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-e17ae43b-284d-4198-9585-f417943c624f/prepaid-cards/trm-2e02da75-a36c-4723-b613-0b64e6f582d9/receipts" + } + ] +} \ No newline at end of file diff --git a/receipt/src/test/resources/prepaid_card_receipt_list.json b/receipt/src/test/resources/prepaid_card_receipt_list_response.json similarity index 83% rename from receipt/src/test/resources/prepaid_card_receipt_list.json rename to receipt/src/test/resources/prepaid_card_receipt_list_response.json index 95715bb7a..e6539804c 100644 --- a/receipt/src/test/resources/prepaid_card_receipt_list.json +++ b/receipt/src/test/resources/prepaid_card_receipt_list_response.json @@ -2,14 +2,21 @@ "data": [ { "journalId": "FISVL_5240220", - "type": "DEPOSIT", + "type": "PREPAID_CARD_SALE", "createdOn": "2019-06-06T22:48:41", - "entry": "CREDIT", + "entry": "DEBIT", "destinationToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", "amount": "10.00", + "fee": "3.00", "currency": "USD", "details": { - "cardNumber": "************0673" + "cardNumber": "************0673", + "clientPaymentId": "AOxXefx9", + "payeeName": "A Person", + "website": "https://api.sandbox.hyperwallet.com", + "notes": "Sample prepaid card payment for the period of June 15th, 2019 to July 23, 2019", + "charityName": "Sample Charity", + "checkNumber": "Sample Check Number" } }, { @@ -27,7 +34,7 @@ { "journalId": "FISA_5240222", "type": "ADJUSTMENT", - "createdOn": "2019-06-06T22:49:17", + "createdOn": "2019-06-01T22:49:17", "entry": "DEBIT", "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", "amount": "8.90", diff --git a/receipt/src/test/resources/prepaid_card_receipt_unknown_type_response.json b/receipt/src/test/resources/prepaid_card_receipt_unknown_type_response.json new file mode 100644 index 000000000..e2d1f2e8c --- /dev/null +++ b/receipt/src/test/resources/prepaid_card_receipt_unknown_type_response.json @@ -0,0 +1,24 @@ +{ + "data": [ + { + "journalId": "FISVL_5240220", + "type": "CARD_WAIVER_FEE", + "createdOn": "2019-06-06T22:48:41", + "entry": "CREDIT", + "destinationToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", + "amount": "15.00", + "currency": "CAD", + "details": { + "cardNumber": "************0673" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-e17ae43b-284d-4198-9585-f417943c624f/prepaid-cards/trm-2e02da75-a36c-4723-b613-0b64e6f582d9/receipts" + } + ] +} \ No newline at end of file From d03e02c1bc422d487a434d8c386b73d95982de32 Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Wed, 3 Jul 2019 13:51:22 -0700 Subject: [PATCH 36/36] Removing unused response file --- .../resources/prepaid_card_receipt_list.json | 96 ------------------- 1 file changed, 96 deletions(-) delete mode 100644 receipt/src/test/resources/prepaid_card_receipt_list.json diff --git a/receipt/src/test/resources/prepaid_card_receipt_list.json b/receipt/src/test/resources/prepaid_card_receipt_list.json deleted file mode 100644 index 95715bb7a..000000000 --- a/receipt/src/test/resources/prepaid_card_receipt_list.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "data": [ - { - "journalId": "FISVL_5240220", - "type": "DEPOSIT", - "createdOn": "2019-06-06T22:48:41", - "entry": "CREDIT", - "destinationToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", - "amount": "10.00", - "currency": "USD", - "details": { - "cardNumber": "************0673" - } - }, - { - "journalId": "FISVL_5240221", - "type": "DEPOSIT", - "createdOn": "2019-06-06T22:48:51", - "entry": "CREDIT", - "destinationToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", - "amount": "5.00", - "currency": "USD", - "details": { - "cardNumber": "************0673" - } - }, - { - "journalId": "FISA_5240222", - "type": "ADJUSTMENT", - "createdOn": "2019-06-06T22:49:17", - "entry": "DEBIT", - "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", - "amount": "8.90", - "currency": "USD", - "details": { - "cardNumber": "************0673" - } - }, - { - "journalId": "FISA_5240223", - "type": "ADJUSTMENT", - "createdOn": "2019-03-31T23:55:17", - "entry": "DEBIT", - "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", - "amount": "7.90", - "currency": "USD", - "details": { - "cardNumber": "************0673" - } - }, - { - "journalId": "FISA_5240224", - "type": "ADJUSTMENT", - "createdOn": "2019-02-28T23:55:17", - "entry": "CREDIT", - "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", - "amount": "6.90", - "currency": "USD", - "details": { - "cardNumber": "************0673" - } - }, - { - "journalId": "FISA_5240225", - "type": "ADJUSTMENT", - "createdOn": "2019-02-23T23:55:17", - "entry": "CREDIT", - "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", - "amount": "3.90", - "currency": "USD", - "details": { - "cardNumber": "************0673" - } - }, - { - "journalId": "FISA_5240226", - "type": "ADJUSTMENT", - "createdOn": "2019-02-21T23:55:17", - "entry": "CREDIT", - "sourceToken": "trm-2e02da75-a36c-4723-b613-0b64e6f582d9", - "amount": "9.92", - "currency": "USD", - "details": { - "cardNumber": "************0673" - } - } - ], - "links": [ - { - "params": { - "rel": "self" - }, - "href": "https://qamaster-hyperwallet.aws.paylution.net/rest/v3/users/usr-e17ae43b-284d-4198-9585-f417943c624f/prepaid-cards/trm-2e02da75-a36c-4723-b613-0b64e6f582d9/receipts" - } - ] -} \ No newline at end of file