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..e9076ea1e --- /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"); + 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("prepaid_card_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/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..f510302c4 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,11 @@ 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; 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 +61,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() { @@ -82,11 +81,6 @@ public void setup() { setLocale(Locale.US); } - @After - public void cleanup() { - ReceiptRepositoryFactory.clearInstance(); - } - @Before public void registerIdlingResource() { IdlingRegistry.getInstance().register(EspressoIdlingResource.getIdlingResource()); @@ -372,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/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index fbfa141a9..2c573851d 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -6,13 +6,18 @@ - - + android:networkSecurityConfig="@xml/network_security_config" + tools:targetApi="n"> + + 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..352ae0913 --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSource.java @@ -0,0 +1,198 @@ +/* + * 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.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; + + /** + * Initialize Prepaid card data source + * + * @param token Prepaid card token identifier, please get this data from HW Platform + */ + PrepaidCardReceiptDataSource(@NonNull final String token) { + mToken = token; + mCalendarYearBeforeNow = Calendar.getInstance(); + mCalendarYearBeforeNow.add(Calendar.YEAR, YEAR_BEFORE_NOW); + } + + /** + * @see 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 PageKeyedDataSource#loadBefore(LoadParams, LoadCallback) + */ + @Override + public void loadBefore(@NonNull final LoadParams params, + @NonNull final LoadCallback callback) { + } + + /** + * @see PageKeyedDataSource#loadAfter(LoadParams, LoadCallback) + */ + @Override + 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) + .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/PrepaidCardReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java new file mode 100644 index 000000000..71edf3f7a --- /dev/null +++ b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/PrepaidCardReceiptDataSourceFactory.java @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * Copyright (c) 2019 Hyperwallet Systems Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.hyperwallet.android.ui.receipt.repository; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.paging.DataSource; + +/** + * Data source factory for PrepaidCard receipt data source, that uses {@link DataSource.Factory} facility + */ +public class PrepaidCardReceiptDataSourceFactory extends DataSource.Factory { + + private final MutableLiveData mDataSourceMutableLiveData; + private final PrepaidCardReceiptDataSource mPrepaidCardReceiptDataSource; + + PrepaidCardReceiptDataSourceFactory(@NonNull final String token) { + super(); + mPrepaidCardReceiptDataSource = new PrepaidCardReceiptDataSource(token); + mDataSourceMutableLiveData = new MutableLiveData<>(); + mDataSourceMutableLiveData.setValue(mPrepaidCardReceiptDataSource); + } + + /** + * Returns observable members of prepaid card receipt data source + */ + LiveData getPrepaidCardReceiptDataSource() { + return mDataSourceMutableLiveData; + } + + /** + * @see 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..4b5fed137 --- /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 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 PrepaidCardReceiptRepository#isLoading() + */ + @Override + public LiveData isLoading() { + if (mIsFetchingData == null) { + mIsFetchingData = mReceiptDataSourceLiveData.getValue().isFetchingData(); + } + return mIsFetchingData; + } + + /** + * @see PrepaidCardReceiptRepository#getErrors() + */ + @Override + public LiveData> getErrors() { + if (mErrorsLiveData == null) { + mErrorsLiveData = mReceiptDataSourceLiveData.getValue().getErrors(); + } + return mErrorsLiveData; + } + + /** + * @see 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/ReceiptRepositoryFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.java deleted file mode 100644 index 8fc76d7ab..000000000 --- a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptRepositoryFactory.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 ReceiptRepository} factory - */ -public class ReceiptRepositoryFactory { - - private static ReceiptRepositoryFactory sInstance; - private final ReceiptRepository mReceiptRepository; - - private ReceiptRepositoryFactory() { - mReceiptRepository = new ReceiptRepositoryImpl(); - } - - /** - * Creates context single instance of this Factory - * - * @return receipt repository factory instance - */ - public static synchronized ReceiptRepositoryFactory getInstance() { - if (sInstance == null) { - sInstance = new ReceiptRepositoryFactory(); - } - return sInstance; - } - - /** - * Clears instance of repository factory - */ - public static void clearInstance() { - sInstance = null; - } - - /** - * @return ReceiptRepository instance implementation - * */ - public ReceiptRepository getReceiptRepository() { - return mReceiptRepository; - } -} diff --git a/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/ReceiptDataSource.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSource.java similarity index 91% 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..28e8ef727 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 - * Receipts V3 API + * UserReceiptDataSource mediates communication to HW API Platform particularly on + * Receipts Users 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,14 +51,14 @@ public class ReceiptDataSource extends PageKeyedDataSource { private LoadCallback mLoadAfterCallback; private LoadParams mLoadAfterParams; - ReceiptDataSource() { + UserReceiptDataSource() { super(); mCalendarYearBeforeNow = Calendar.getInstance(); mCalendarYearBeforeNow.add(Calendar.YEAR, YEAR_BEFORE_NOW); } /** - * @see {@link PageKeyedDataSource#loadInitial(LoadInitialParams, LoadInitialCallback)} + * @see PageKeyedDataSource#loadInitial(LoadInitialParams, LoadInitialCallback) */ @Override public void loadInitial(@NonNull final LoadInitialParams params, @@ -108,18 +108,18 @@ public Handler getHandler() { /** * Unused in this case * - * @see {@link PageKeyedDataSource#loadBefore(LoadParams, LoadCallback)} + * @see 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)} + * @see 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/repository/ReceiptDataSourceFactory.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptDataSourceFactory.java similarity index 67% 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..e974a0c05 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 @@ -22,33 +22,33 @@ 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 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 + * Returns observable members of user receipt data source */ - LiveData getReceiptDataSource() { + LiveData getUserReceiptDataSource() { return mDataSourceMutableLiveData; } /** - * @see {@link DataSource.Factory#create()} + * @see DataSource.Factory#create() */ @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 89% 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..7c72ab664 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,14 +26,14 @@ /** * Receipt Repository Contract */ -public interface ReceiptRepository { +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/ReceiptRepositoryImpl.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/repository/UserReceiptRepositoryImpl.java similarity index 79% 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..07a8fbdb9 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,29 +25,29 @@ 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(); + public UserReceiptRepositoryImpl() { + mDataSourceFactory = new UserReceiptDataSourceFactory(); + mReceiptDataSourceLiveData = mDataSourceFactory.getUserReceiptDataSource(); } /** - * @see {@link ReceiptRepository#loadReceipts()} + * @see UserReceiptRepository#loadUserReceipts() */ @Override - public LiveData> loadReceipts() { + public LiveData> loadUserReceipts() { if (mReceiptsLiveData == null) { PagedList.Config config = new PagedList.Config.Builder() .setPageSize(PAGE_SIZE) @@ -60,7 +60,7 @@ public LiveData> loadReceipts() { } /** - * @see {@link ReceiptRepository#isLoading()} + * @see UserReceiptRepository#isLoading() */ @Override public LiveData isLoading() { @@ -71,7 +71,7 @@ public LiveData isLoading() { } /** - * @see {@link ReceiptRepository#getErrors()} + * @see UserReceiptRepository#getErrors() * */ @Override public LiveData> getErrors() { @@ -82,7 +82,7 @@ public LiveData> getErrors() { } /** - * @see {@link ReceiptRepository#retryLoadReceipt()} + * @see UserReceiptRepository#retryLoadReceipt() * */ @Override public void retryLoadReceipt() { 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..b774436d4 --- /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_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 e1fd220a2..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 @@ -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.ReceiptViewModel; import java.text.DecimalFormat; import java.util.Calendar; @@ -58,13 +58,13 @@ public class ListReceiptFragment extends Fragment { private ListReceiptAdapter mListReceiptAdapter; private RecyclerView mListReceiptsView; - private ListReceiptViewModel mListReceiptViewModel; + private ReceiptViewModel mReceiptViewModel; private View mProgressBar; /** * Please don't use this constructor this is reserved for Android Core Framework * - * @see {@link ListReceiptFragment#newInstance()} instead. + * @see #newInstance() */ public ListReceiptFragment() { setRetainInstance(true); @@ -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); + mReceiptViewModel = ViewModelProviders.of(requireActivity()).get( + ReceiptViewModel.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(mReceiptViewModel, 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>() { + mReceiptViewModel.getReceiptList().observe(getViewLifecycleOwner(), new Observer>() { @Override public void onChanged(PagedList receipts) { mListReceiptAdapter.submitList(receipts); } }); - mListReceiptViewModel.isLoadingData().observe(getViewLifecycleOwner(), new Observer() { + mReceiptViewModel.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(); + mReceiptViewModel.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 ReceiptViewModel mReceiptViewModel; - ListReceiptAdapter(@NonNull final ListReceiptViewModel receiptViewModel, + ListReceiptAdapter(@NonNull final ReceiptViewModel receiptViewModel, @NonNull final DiffUtil.ItemCallback diffCallback) { super(diffCallback); mReceiptViewModel = receiptViewModel; @@ -199,25 +199,25 @@ public void onBindViewHolder(@NonNull final ReceiptViewHolder holder, final int class ReceiptViewHolder extends RecyclerView.ViewHolder { - private ListReceiptViewModel mListReceiptViewModel; + private ReceiptViewModel mListUserReceiptViewModel; private View mView; - ReceiptViewHolder(@NonNull final ListReceiptViewModel receiptViewModel, + ReceiptViewHolder(@NonNull final ReceiptViewModel 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); } }); - // 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 ListReceiptViewModel 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/java/com/hyperwallet/android/ui/receipt/view/ListReceiptActivity.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/view/ListUserReceiptActivity.java similarity index 83% 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..bc66e9609 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,21 @@ 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.UserReceiptRepositoryImpl; +import com.hyperwallet.android.ui.receipt.viewmodel.ListUserReceiptViewModel; +import com.hyperwallet.android.ui.receipt.viewmodel.ReceiptViewModel; import java.util.List; -public class ListReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback, +public class ListUserReceiptActivity extends AppCompatActivity implements OnNetworkErrorCallback, ListDetailNavigator> { - private ListReceiptViewModel mListReceiptViewModel; + private ReceiptViewModel mReceiptViewModel; @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 +66,11 @@ public void onClick(View v) { } }); - ReceiptRepositoryFactory factory = ReceiptRepositoryFactory.getInstance(); - mListReceiptViewModel = ViewModelProviders.of(this, new ListReceiptViewModel - .ListReceiptViewModelFactory(factory.getReceiptRepository())) - .get(ListReceiptViewModel.class); + mReceiptViewModel = ViewModelProviders.of(this, new ListUserReceiptViewModel + .ListReceiptViewModelFactory(new UserReceiptRepositoryImpl())) + .get(ReceiptViewModel.class); - mListReceiptViewModel.getReceiptErrors().observe(this, new Observer>() { + mReceiptViewModel.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>() { + mReceiptViewModel.getDetailNavigation().observe(this, new Observer>() { @Override public void onChanged(Event event) { navigate(event); @@ -91,12 +91,6 @@ public void onChanged(Event event) { } } - @Override - protected void onDestroy() { - super.onDestroy(); - ReceiptRepositoryFactory.clearInstance(); - } - @Override protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { super.onActivityResult(requestCode, resultCode, data); 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 new file mode 100644 index 000000000..73f697bca --- /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 ReceiptViewModel#isLoadingData() + */ + @Override + public LiveData isLoadingData() { + return mPrepaidCardReceiptRepository.isLoading(); + } + + /** + * @see ReceiptViewModel#getReceiptErrors() + */ + @Override + public LiveData> getReceiptErrors() { + return mErrorEvent; + } + + /** + * @see ReceiptViewModel#getReceiptList() + */ + @Override + public LiveData> getReceiptList() { + return mPrepaidCardReceiptRepository.loadPrepaidCardReceipts(); + } + + /** + * @see ReceiptViewModel#retryLoadReceipts() + */ + @Override + public void retryLoadReceipts() { + mPrepaidCardReceiptRepository.retryLoadReceipt(); + } + + /** + * @see ReceiptViewModel#getDetailNavigation() + */ + @Override + public LiveData> getDetailNavigation() { + return mDetailNavigation; + } + + /** + * @see ReceiptViewModel#setDetailNavigation(Receipt) + */ + @Override + public void setDetailNavigation(@NonNull Receipt receipt) { + mDetailNavigation.postValue(new Event<>(receipt)); + } + + /** + * @see 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/ListReceiptViewModel.java b/receipt/src/main/java/com/hyperwallet/android/ui/receipt/viewmodel/ListUserReceiptViewModel.java similarity index 62% 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..9b9b63b2c 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 ReceiptViewModel { 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.loadUserReceipts(); // register one time error event observer mErrorEventObserver = new Observer>() { @@ -48,55 +48,77 @@ public void onChanged(Event event) { mErrorEvent.postValue(event); } }; - mReceiptRepository.getErrors().observeForever(mErrorEventObserver); + mUserReceiptRepository.getErrors().observeForever(mErrorEventObserver); } + /** + * @see ReceiptViewModel#isLoadingData() + */ public LiveData isLoadingData() { - return mReceiptRepository.isLoading(); + return mUserReceiptRepository.isLoading(); } + /** + * @see ReceiptViewModel#getReceiptErrors() + */ public LiveData> getReceiptErrors() { return mErrorEvent; } + /** + * @see ReceiptViewModel#getReceiptList() + */ public LiveData> getReceiptList() { - return mReceiptRepository.loadReceipts(); + return mUserReceiptRepository.loadUserReceipts(); } + /** + * @see ReceiptViewModel#retryLoadReceipts() + * */ public void retryLoadReceipts() { - mReceiptRepository.retryLoadReceipt(); + mUserReceiptRepository.retryLoadReceipt(); } + /** + * @see ReceiptViewModel#getDetailNavigation() + * */ public LiveData> getDetailNavigation() { return mDetailNavigation; } + /** + * @see ReceiptViewModel#setDetailNavigation(Receipt) + * */ public void setDetailNavigation(@NonNull final Receipt receipt) { mDetailNavigation.postValue(new Event<>(receipt)); } + /** + * @see ViewModel#onCleared() + * */ @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/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); +} 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/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/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 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/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..f703e7810 --- /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.spy; +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.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; + + private PrepaidCardReceiptDataSource mPrepaidCardReceiptDataSource; + + @Before + public void setUp() { + mPrepaidCardReceiptDataSource = spy(new PrepaidCardReceiptDataSource("test-token")); + doReturn(mHyperwallet).when(mPrepaidCardReceiptDataSource).getHyperwallet(); + } + + + @Test + public void testLoadInitial_returnsReceipts() throws Exception { + String json = mExternalResourceManager.getResourceContent("prepaid_card_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("prepaid_card_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()); + } +} 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/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 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(); 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..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,7 +32,8 @@ 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.ListPrepaidCardReceiptActivity; +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 +83,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 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); + 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; } /** @@ -107,6 +119,4 @@ public Intent getIntentAddTransferMethodActivity(@NonNull final Context context, intent.putExtra(EXTRA_TRANSFER_METHOD_PROFILE_TYPE, profileType); return intent; } - - }