From 4d7386ba7df199a2281561d485e682d5c1585f4a Mon Sep 17 00:00:00 2001 From: azakrevska-epam Date: Thu, 6 Jun 2019 14:20:27 +0300 Subject: [PATCH 1/6] HW-53401. Added ui tests for list receipts --- .../transfermethod/ui/ListReceiptsTest.java | 150 ++++++++++++++++++ .../test/resources/receipt_list_response.json | 64 ++++++++ .../receipt_list_single_receipt_response.json | 30 ++++ 3 files changed, 244 insertions(+) create mode 100644 ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java create mode 100644 ui/src/test/resources/receipt_list_response.json create mode 100644 ui/src/test/resources/receipt_list_single_receipt_response.json diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java new file mode 100644 index 000000000..637ca9b6b --- /dev/null +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java @@ -0,0 +1,150 @@ +package com.hyperwallet.android.transfermethod.ui; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withParent; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.instanceOf; + +import static java.net.HttpURLConnection.HTTP_NO_CONTENT; +import static java.net.HttpURLConnection.HTTP_OK; + +import static com.hyperwallet.android.util.EspressoUtils.atPosition; + +import android.widget.TextView; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ActivityTestRule; + +import com.hyperwallet.android.Hyperwallet; +import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.receipt.view.ListReceiptActivity; +import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.rule.HyperwalletMockWebServer; +import com.hyperwallet.android.ui.repository.RepositoryFactory; +import com.hyperwallet.android.util.RecyclerViewCountAssertion; +import com.hyperwallet.android.util.TestAuthenticationProvider; + +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class ListReceiptsTest { + + @ClassRule + public static HyperwalletExternalResourceManager sResourceManager = new HyperwalletExternalResourceManager(); + @Rule + public HyperwalletMockWebServer mMockWebServer = new HyperwalletMockWebServer(8080); + @Rule + public ActivityTestRule mActivityTestRule = + new ActivityTestRule<>(ListReceiptActivity.class, true, false); + + @Before + public void setup() { + Hyperwallet.getInstance(new TestAuthenticationProvider()); + + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("authentication_token_response.json")).mock(); + } + + @After + public void cleanup() { + RepositoryFactory.clearInstance(); + } + + @Test + public void testListReceipts_userHasMultiplereceipts() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_list_response.json")).mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("November 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("+ 20.00"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("November 01, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("November 02, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("CAD"))))); + + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("Card Activation Fee"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("- 1.95"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("November 10, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(3, hasDescendant(withText("December 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("Card Load"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("- 18.05"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("December 01, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(4)); + } + + @Test + public void testListReceipt_userHasSingleReceipt() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_list_single_receipt_response.json")).mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("November 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("November 02, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("CAD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); + } + + @Test + public void testListReceipt_userHasNoReceipts() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + + // run test + mActivityTestRule.launchActivity(null); + + onView(withId(R.id.toolbar)).check(matches(isDisplayed())); + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + //todo: check empty view when it will be ready + } +} diff --git a/ui/src/test/resources/receipt_list_response.json b/ui/src/test/resources/receipt_list_response.json new file mode 100644 index 000000000..fa12f7f54 --- /dev/null +++ b/ui/src/test/resources/receipt_list_response.json @@ -0,0 +1,64 @@ +{ + "count": 4, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051579", + "type": "PAYMENT", + "createdOn": "2017-11-01T17:08:58", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "20.00", + "fee": "0.00", + "currency": "USD", + "details": { + "clientPaymentId": "8OxXefx5", + "payeeName": "A Person" + } + }, + { + "journalId": "3051581", + "type": "PAYMENT", + "createdOn": "2017-11-02T17:09:07", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "25.00", + "fee": "0.00", + "currency": "CAD", + "details": { + "clientPaymentId": "Q3SVvpv0", + "payeeName": "A Person" + } + }, + { + "journalId": "3051582", + "type": "CARD_ACTIVATION_FEE", + "createdOn": "2017-11-10T17:09:16", + "entry": "DEBIT", + "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "1.95", + "currency": "USD" + }, + { + "journalId": "3051590", + "type": "TRANSFER_TO_PREPAID_CARD", + "createdOn": "2017-12-01T17:12:18", + "entry": "DEBIT", + "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "destinationToken": "trm-12345", + "amount": "18.05", + "currency": "USD" + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file diff --git a/ui/src/test/resources/receipt_list_single_receipt_response.json b/ui/src/test/resources/receipt_list_single_receipt_response.json new file mode 100644 index 000000000..0b4896205 --- /dev/null +++ b/ui/src/test/resources/receipt_list_single_receipt_response.json @@ -0,0 +1,30 @@ +{ + "count": 1, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051581", + "type": "PAYMENT", + "createdOn": "2017-11-02T17:09:07", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "25.00", + "fee": "0.00", + "currency": "CAD", + "details": { + "clientPaymentId": "ABC1234", + "payeeName": "A Person" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file From 02daeb0cd87e80c48c87bb1b57ee56f5e572266c Mon Sep 17 00:00:00 2001 From: azakrevska-epam Date: Fri, 7 Jun 2019 16:17:08 +0300 Subject: [PATCH 2/6] HW-53401. Renamed tests for list receipts --- .../transfermethod/ui/ListReceiptsTest.java | 49 ++++++++++++++----- ...onse.json => receipt_credit_response.json} | 2 +- .../resources/receipt_debit_response.json | 25 ++++++++++ .../test/resources/receipt_list_response.json | 8 +-- 4 files changed, 67 insertions(+), 17 deletions(-) rename ui/src/test/resources/{receipt_list_single_receipt_response.json => receipt_credit_response.json} (93%) create mode 100644 ui/src/test/resources/receipt_debit_response.json diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java index 637ca9b6b..2bb3e86b2 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java @@ -62,7 +62,7 @@ public void cleanup() { } @Test - public void testListReceipts_userHasMultiplereceipts() { + public void testListReceipts_userHasMultipleTransactions() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_list_response.json")).mock(); @@ -75,19 +75,19 @@ public void testListReceipts_userHasMultiplereceipts() { onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); onView(withId(R.id.list_receipts)) - .check(matches(atPosition(0, hasDescendant(withText("November 2017"))))); + .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Payment"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("+ 20.00"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("November 01, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("June 07, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("Payment"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("+ 25.00"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("November 02, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("June 02, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("CAD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, @@ -95,25 +95,25 @@ public void testListReceipts_userHasMultiplereceipts() { onView(withId(R.id.list_receipts)).check( matches(atPosition(2, hasDescendant(withText("Card Activation Fee"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("- 1.95"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("November 10, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("June 01, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)) - .check(matches(atPosition(3, hasDescendant(withText("December 2017"))))); + .check(matches(atPosition(3, hasDescendant(withText("December 2018"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("Card Load"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("- 18.05"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("December 01, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("December 01, 2018"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(4)); } @Test - public void testListReceipt_userHasSingleReceipt() { + public void testListReceipts_displayCreditTransaction() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager - .getResourceContent("receipt_list_single_receipt_response.json")).mock(); + .getResourceContent("receipt_credit_response.json")).mock(); // run test mActivityTestRule.launchActivity(null); @@ -124,19 +124,44 @@ public void testListReceipt_userHasSingleReceipt() { onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); onView(withId(R.id.list_receipts)) - .check(matches(atPosition(0, hasDescendant(withText("November 2017"))))); + .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Payment"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("November 02, 2017"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("June 02, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("CAD"))))); onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); } @Test - public void testListReceipt_userHasNoReceipts() { + public void testListReceipts_displayDebitTransaction() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_debit_response.json")).mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("May 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Card Load"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("- 18.05"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("May 02, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); + } + + @Test + public void testListReceipt_userHasNoTransactions() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); // run test diff --git a/ui/src/test/resources/receipt_list_single_receipt_response.json b/ui/src/test/resources/receipt_credit_response.json similarity index 93% rename from ui/src/test/resources/receipt_list_single_receipt_response.json rename to ui/src/test/resources/receipt_credit_response.json index 0b4896205..4351d17a2 100644 --- a/ui/src/test/resources/receipt_list_single_receipt_response.json +++ b/ui/src/test/resources/receipt_credit_response.json @@ -6,7 +6,7 @@ { "journalId": "3051581", "type": "PAYMENT", - "createdOn": "2017-11-02T17:09:07", + "createdOn": "2019-06-02T17:09:07", "entry": "CREDIT", "sourceToken": "act-12345", "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", diff --git a/ui/src/test/resources/receipt_debit_response.json b/ui/src/test/resources/receipt_debit_response.json new file mode 100644 index 000000000..8ed756455 --- /dev/null +++ b/ui/src/test/resources/receipt_debit_response.json @@ -0,0 +1,25 @@ +{ + "count": 1, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051590", + "type": "TRANSFER_TO_PREPAID_CARD", + "createdOn": "2019-05-02T17:12:18", + "entry": "DEBIT", + "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "destinationToken": "trm-12345", + "amount": "18.05", + "currency": "USD" + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file diff --git a/ui/src/test/resources/receipt_list_response.json b/ui/src/test/resources/receipt_list_response.json index fa12f7f54..7e7cc58af 100644 --- a/ui/src/test/resources/receipt_list_response.json +++ b/ui/src/test/resources/receipt_list_response.json @@ -6,7 +6,7 @@ { "journalId": "3051579", "type": "PAYMENT", - "createdOn": "2017-11-01T17:08:58", + "createdOn": "2019-06-07T17:08:58", "entry": "CREDIT", "sourceToken": "act-12345", "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", @@ -21,7 +21,7 @@ { "journalId": "3051581", "type": "PAYMENT", - "createdOn": "2017-11-02T17:09:07", + "createdOn": "2019-06-02T16:09:07", "entry": "CREDIT", "sourceToken": "act-12345", "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", @@ -36,7 +36,7 @@ { "journalId": "3051582", "type": "CARD_ACTIVATION_FEE", - "createdOn": "2017-11-10T17:09:16", + "createdOn": "2019-06-01T11:09:16", "entry": "DEBIT", "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", "amount": "1.95", @@ -45,7 +45,7 @@ { "journalId": "3051590", "type": "TRANSFER_TO_PREPAID_CARD", - "createdOn": "2017-12-01T17:12:18", + "createdOn": "2018-12-01T17:12:18", "entry": "DEBIT", "sourceToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", "destinationToken": "trm-12345", From beb852992a52d4955d6ab5a8ffe4ef796fa1d4c0 Mon Sep 17 00:00:00 2001 From: azakrevska-epam Date: Fri, 7 Jun 2019 22:49:03 +0300 Subject: [PATCH 3/6] HW-52031. Added test for locale --- .../transfermethod/ui/ListReceiptsTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java index 2bb3e86b2..3f871af7b 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java +++ b/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java @@ -16,8 +16,12 @@ import static com.hyperwallet.android.util.EspressoUtils.atPosition; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; import android.widget.TextView; +import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; @@ -37,6 +41,8 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Locale; + @RunWith(AndroidJUnit4.class) public class ListReceiptsTest { @@ -54,6 +60,7 @@ public void setup() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("authentication_token_response.json")).mock(); + setLocale(Locale.US); } @After @@ -172,4 +179,36 @@ public void testListReceipt_userHasNoTransactions() { .check(matches(withText(R.string.title_activity_receipt_list))); //todo: check empty view when it will be ready } + + @Test + public void testListReceipts_checkDateTextOnLocaleChange() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_debit_response.json")).mock(); + setLocale(Locale.ITALY); + // run test + mActivityTestRule.launchActivity(null); + // assert + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("maggio 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("maggio 02, 2019"))))); + mActivityTestRule.finishActivity(); + setLocale(Locale.US); + mActivityTestRule.launchActivity(null); + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("May 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("May 02, 2019"))))); + } + + private void setLocale(Locale locale) { + Context context = ApplicationProvider.getApplicationContext(); + Locale.setDefault(locale); + Resources resources = context.getResources(); + Configuration configuration = resources.getConfiguration(); + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN) { + configuration.setLocale(locale); + } else { + configuration.locale = locale; + } + resources.updateConfiguration(configuration, resources.getDisplayMetrics()); + } } From 86b55e37b21d21cfd0b16b9fd79dae15f67d8d2e Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Mon, 10 Jun 2019 10:40:34 -0700 Subject: [PATCH 4/6] Task/hw 53401 moving receipts automation (#36) --- receipt/build.gradle | 6 + .../android/receipt}/ListReceiptsTest.java | 59 ++++-- .../HyperwalletExternalResourceManager.java | 3 +- .../rule/HyperwalletMockWebServer.java | 115 +++++++++++ .../android/util/EspressoUtils.java | 187 ++++++++++++++++++ .../android/util/NestedScrollToAction.java | 41 ++++ .../util/RecyclerViewCountAssertion.java | 30 +++ .../util/TestAuthenticationProvider.java | 51 +++++ receipt/src/main/AndroidManifest.xml | 4 +- .../main/res/xml/network_security_config.xml | 6 + .../repository/ReceiptDataSourceTest.java | 2 +- .../HyperwalletExternalResourceManager.java | 72 +++++++ .../authentication_token_response.json | 3 + .../resources/receipt_credit_response.json | 0 .../resources/receipt_debit_response.json | 0 .../test/resources/receipt_list_response.json | 0 ui/src/androidTest/AndroidManifest.xml | 9 - 17 files changed, 555 insertions(+), 33 deletions(-) rename {ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui => receipt/src/androidTest/java/com/hyperwallet/android/receipt}/ListReceiptsTest.java (78%) rename receipt/src/{test/java/com/hyperwallet/android/receipt => androidTest/java/com/hyperwallet/android}/rule/HyperwalletExternalResourceManager.java (98%) create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java create mode 100644 receipt/src/main/res/xml/network_security_config.xml create mode 100644 receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java create mode 100644 receipt/src/test/resources/authentication_token_response.json rename {ui => receipt}/src/test/resources/receipt_credit_response.json (100%) rename {ui => receipt}/src/test/resources/receipt_debit_response.json (100%) rename {ui => receipt}/src/test/resources/receipt_list_response.json (100%) delete mode 100644 ui/src/androidTest/AndroidManifest.xml diff --git a/receipt/build.gradle b/receipt/build.gradle index dac1fd822..6aa8d9d42 100644 --- a/receipt/build.gradle +++ b/receipt/build.gradle @@ -11,7 +11,13 @@ dependencies { implementation "androidx.paging:paging-runtime:$pagingRuntimeVersion" testImplementation "org.robolectric:robolectric:$robolectricVersion" + androidTestImplementation "androidx.test:rules:$testRulesVersion" + androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion" + androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion" + androidTestImplementation "com.squareup.okhttp3:mockwebserver:$mockServerVersion" + androidTestImplementation "com.squareup.leakcanary:leakcanary-android-instrumentation:$leakcanaryVersion" + androidTestImplementation "com.squareup.leakcanary:leakcanary-support-fragment:$leakcanaryVersion" } def aarFile = file("$buildDir/outputs/aar/receipt-$version" + ".aar") diff --git a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java similarity index 78% rename from ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java rename to receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java index 3f871af7b..d0a99c292 100644 --- a/ui/src/androidTest/java/com/hyperwallet/android/transfermethod/ui/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.transfermethod.ui; +package com.hyperwallet.android.receipt; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.assertion.ViewAssertions.matches; @@ -26,11 +26,10 @@ import androidx.test.rule.ActivityTestRule; import com.hyperwallet.android.Hyperwallet; -import com.hyperwallet.android.hyperwallet_ui.R; +import com.hyperwallet.android.receipt.repository.ReceiptRepositoryFactory; import com.hyperwallet.android.receipt.view.ListReceiptActivity; import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; import com.hyperwallet.android.rule.HyperwalletMockWebServer; -import com.hyperwallet.android.ui.repository.RepositoryFactory; import com.hyperwallet.android.util.RecyclerViewCountAssertion; import com.hyperwallet.android.util.TestAuthenticationProvider; @@ -60,12 +59,13 @@ public void setup() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("authentication_token_response.json")).mock(); + setLocale(Locale.US); } @After public void cleanup() { - RepositoryFactory.clearInstance(); + ReceiptRepositoryFactory.clearInstance(); } @Test @@ -85,33 +85,44 @@ public void testListReceipts_userHasMultipleTransactions() { .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Payment"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("+ 20.00"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("June 07, 2019"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("+ 20.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 07, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("Payment"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("+ 25.00"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("June 02, 2019"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(1, hasDescendant(withText("June 02, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(1, hasDescendant(withText("CAD"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(2, hasDescendant(withText("Card Activation Fee"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("- 1.95"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("June 01, 2019"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("- 1.95"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(2, hasDescendant(withText("June 01, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(2, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)) .check(matches(atPosition(3, hasDescendant(withText("December 2018"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("Card Load"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("- 18.05"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("December 01, 2018"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("Card Load"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("- 18.05"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(3, hasDescendant(withText("December 01, 2018"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(3, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(4)); @@ -134,9 +145,12 @@ public void testListReceipts_displayCreditTransaction() { .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Payment"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("June 02, 2019"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("Payment"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 02, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("CAD"))))); onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); @@ -159,9 +173,12 @@ public void testListReceipts_displayDebitTransaction() { .check(matches(atPosition(0, hasDescendant(withText("May 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("Card Load"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("- 18.05"))))); - onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("May 02, 2019"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("Card Load"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("- 18.05"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("May 02, 2019"))))); onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("USD"))))); onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/rule/HyperwalletExternalResourceManager.java b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java similarity index 98% rename from receipt/src/test/java/com/hyperwallet/android/receipt/rule/HyperwalletExternalResourceManager.java rename to receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java index 0c5f6a743..e7e546063 100644 --- a/receipt/src/test/java/com/hyperwallet/android/receipt/rule/HyperwalletExternalResourceManager.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java @@ -1,4 +1,4 @@ -package com.hyperwallet.android.receipt.rule; +package com.hyperwallet.android.rule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; @@ -35,6 +35,7 @@ public String getResourceContent(final String resourceName) { } private String getContent(final String resourceName) { + URL resource = classLoader.getResource(resourceName); InputStream inputStream = null; Writer writer = new StringWriter(); diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java new file mode 100644 index 000000000..9f42f6128 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/rule/HyperwalletMockWebServer.java @@ -0,0 +1,115 @@ +package com.hyperwallet.android.rule; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import java.io.IOException; +import java.net.HttpURLConnection; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +public final class HyperwalletMockWebServer extends TestWatcher { + + private MockWebServer mServer; + private int port; + + public HyperwalletMockWebServer(int port) { + this.port = port; + } + + @Override + protected void starting(Description description) { + super.starting(description); + mServer = new MockWebServer(); + try { + mServer.start(port); + } catch (IOException e) { + throw new IllegalStateException("Unable to start mock server", e); + } + } + + @Override + protected void finished(Description description) { + super.finished(description); + try { + mServer.shutdown(); + mServer.close(); + } catch (IOException e) { + throw new IllegalStateException("Un error occurred when shutting down mock server", e); + } + } + + public HyperwalletMockResponse mockResponse() { + return new Builder(mServer).build(); + } + + public MockWebServer getServer() { + return mServer; + } + + public static class HyperwalletMockResponse { + + private String path; + private String body; + private int httpResponseCode; + private Builder builder; + + HyperwalletMockResponse(Builder builder) { + this.path = builder.path; + this.httpResponseCode = builder.responseCode; + this.body = builder.body; + this.builder = builder; + } + + public HyperwalletMockResponse withHttpResponseCode(final int code) { + builder.responseCode(code); + return builder.build(); + } + + public HyperwalletMockResponse withBody(final String body) { + builder.body(body); + return builder.build(); + } + + public void mock() { + mockRequest(); + } + + private String mockRequest() { + builder.server.enqueue(new MockResponse().setResponseCode(httpResponseCode).setBody(body)); + return builder.server.url(path).toString(); + } + + } + + private static class Builder { + + private String path; + private String body; + private int responseCode; + private MockWebServer server; + + + Builder(final MockWebServer server) { + this.path = ""; + this.responseCode = HttpURLConnection.HTTP_OK; + this.body = ""; + this.server = server; + } + + Builder responseCode(final int code) { + this.responseCode = code; + return this; + } + + Builder body(final String body) { + this.body = body; + return this; + } + + HyperwalletMockResponse build() { + return new HyperwalletMockResponse(this); + } + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java new file mode 100644 index 000000000..92a711f96 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/EspressoUtils.java @@ -0,0 +1,187 @@ +package com.hyperwallet.android.util; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.matcher.BoundedMatcher; + +import com.google.android.material.textfield.TextInputLayout; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.Objects; + +public class EspressoUtils { + + public static Matcher withHint(final String expectedHint) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + + String hint = Objects.toString(((TextInputLayout) view).getHint()); + return expectedHint.equals(hint); + } + + @Override + public void describeTo(Description description) { + description.appendText(expectedHint); + } + }; + } + + public static Matcher hasErrorText(final String expectedErrorMessage) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + + String errorMessage = Objects.toString(((TextInputLayout) view).getError()); + return expectedErrorMessage.equals(errorMessage); + } + + @Override + public void describeTo(Description description) { + description.appendText(expectedErrorMessage); + } + }; + } + + public static Matcher hasErrorText(final int resourceId) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + String expectedErrorMessage = view.getResources().getString(resourceId); + String errorMessage = Objects.toString(((TextInputLayout) view).getError()); + + return expectedErrorMessage.equals(errorMessage); + } + + @Override + public void describeTo(Description description) { + } + }; + } + + public static Matcher withDrawable(final int resourceId) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof ImageView)) { + return false; + } + + Drawable drawable = ((ImageView) view).getDrawable(); + if (drawable == null) { + return false; + } + Drawable expectedDrawable = view.getContext().getResources().getDrawable(resourceId); + + Bitmap bitmap = getBitmap(drawable); + Bitmap expectedBitmap = getBitmap(expectedDrawable); + + return bitmap.sameAs(expectedBitmap); + } + + @Override + public void describeTo(Description description) { + } + }; + } + + public static Matcher atPosition(final int position, @NonNull final Matcher matcher) { + return new BoundedMatcher(RecyclerView.class) { + + @Override + protected boolean matchesSafely(final RecyclerView view) { + RecyclerView.ViewHolder viewHolder = view.findViewHolderForAdapterPosition(position); + + if (viewHolder == null) { + return false; + } + + return matcher.matches(viewHolder.itemView); + } + + @Override + public void describeTo(Description description) { + description.appendText("has item at position " + position + ": "); + matcher.describeTo(description); + } + }; + } + + public static ViewAction nestedScrollTo() { + return ViewActions.actionWithAssertions(new NestedScrollToAction()); + } + + private static Bitmap getBitmap(Drawable drawable) { + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } + + public static Matcher hasNoErrorText() { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof TextInputLayout)) { + return false; + } + return ((TextInputLayout) view).getError() == null; + } + + @Override + public void describeTo(Description description) { + description.appendText("has no error text: "); + } + }; + } + + public static Matcher hasEmptyText() { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof EditText)) { + return false; + } + String text = ((EditText) view).getText().toString(); + + return text.isEmpty(); + } + + @Override + public void describeTo(Description description) { + } + }; + } +} + diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java new file mode 100644 index 000000000..392867387 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/NestedScrollToAction.java @@ -0,0 +1,41 @@ +package com.hyperwallet.android.util; + +import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; +import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.anyOf; + +import android.view.View; + +import androidx.core.widget.NestedScrollView; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.ScrollToAction; +import androidx.test.espresso.matcher.ViewMatchers; + +import org.hamcrest.Matcher; + +public class NestedScrollToAction implements ViewAction { + private static final String TAG = ScrollToAction.class.getSimpleName(); + + @SuppressWarnings("unchecked") + @Override + public Matcher getConstraints() { + return allOf( + withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), + isDescendantOfA( + anyOf(isAssignableFrom(NestedScrollView.class)))); + } + + @Override + public void perform(UiController uiController, View view) { + new ScrollToAction().perform(uiController, view); + } + + @Override + public String getDescription() { + return "scroll to"; + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java new file mode 100644 index 000000000..bb3aecaff --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/RecyclerViewCountAssertion.java @@ -0,0 +1,30 @@ +package com.hyperwallet.android.util; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.ViewAssertion; + +public class RecyclerViewCountAssertion implements ViewAssertion { + private final int mCount; + + public RecyclerViewCountAssertion(int count) { + this.mCount = count; + } + + @Override + public void check(View view, NoMatchingViewException noViewFoundException) { + if (noViewFoundException != null) { + throw noViewFoundException; + } + + RecyclerView recyclerView = (RecyclerView) view; + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + + assertThat(adapter.getItemCount(), is(mCount)); + } +} diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java b/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java new file mode 100644 index 000000000..686ccbf30 --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/util/TestAuthenticationProvider.java @@ -0,0 +1,51 @@ +package com.hyperwallet.android.util; + +import com.hyperwallet.android.HyperwalletAuthenticationTokenListener; +import com.hyperwallet.android.HyperwalletAuthenticationTokenProvider; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.UUID; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +public class TestAuthenticationProvider implements HyperwalletAuthenticationTokenProvider { + + public static final MediaType JSON + = MediaType.get("application/json; charset=utf-8"); + private static final String mBaseUrl = "http://localhost:8080/rest/v3/users/{0}/authentication-token"; + private static final String mUserToken = "user_token"; + + @Override + public void retrieveAuthenticationToken(final HyperwalletAuthenticationTokenListener authenticationTokenListener) { + + OkHttpClient client = new OkHttpClient(); + + String payload = "{}"; + String baseUrl = MessageFormat.format(mBaseUrl, mUserToken); + + RequestBody body = RequestBody.create(JSON, payload); + Request request = new Request.Builder() + .url(baseUrl) + .post(body) + .build(); + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + authenticationTokenListener.onFailure(UUID.randomUUID(), e.getMessage()); + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + authenticationTokenListener.onSuccess(response.body().string()); + } + }); + } +} diff --git a/receipt/src/main/AndroidManifest.xml b/receipt/src/main/AndroidManifest.xml index 251bb4f88..3039f6d18 100644 --- a/receipt/src/main/AndroidManifest.xml +++ b/receipt/src/main/AndroidManifest.xml @@ -2,7 +2,9 @@ - + + + diff --git a/receipt/src/main/res/xml/network_security_config.xml b/receipt/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..5e4ba9c97 --- /dev/null +++ b/receipt/src/main/res/xml/network_security_config.xml @@ -0,0 +1,6 @@ + + + + localhost + + \ No newline at end of file diff --git a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java index c4f4894e5..0c71e1b61 100644 --- a/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java +++ b/receipt/src/test/java/com/hyperwallet/android/receipt/repository/ReceiptDataSourceTest.java @@ -27,7 +27,7 @@ import com.hyperwallet.android.model.paging.HyperwalletPageList; import com.hyperwallet.android.model.receipt.Receipt; import com.hyperwallet.android.model.receipt.ReceiptQueryParam; -import com.hyperwallet.android.receipt.rule.HyperwalletExternalResourceManager; +import com.hyperwallet.android.rule.HyperwalletExternalResourceManager; import org.hamcrest.Matchers; import org.json.JSONObject; diff --git a/receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java b/receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java new file mode 100644 index 000000000..9061af9b8 --- /dev/null +++ b/receipt/src/test/java/com/hyperwallet/android/rule/HyperwalletExternalResourceManager.java @@ -0,0 +1,72 @@ +package com.hyperwallet.android.rule; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class HyperwalletExternalResourceManager extends TestWatcher { + + private static final String EMPTY = ""; + private ClassLoader classLoader; + private Logger logger; + + @Override + protected void starting(Description description) { + super.starting(description); + classLoader = description.getTestClass().getClassLoader(); + logger = Logger.getLogger(description.getTestClass().getName()); + } + + public String getResourceContent(final String resourceName) { + if (resourceName == null) { + throw new IllegalArgumentException("Parameter resourceName cannot be null"); + } + + return getContent(resourceName); + } + + private String getContent(final String resourceName) { + URL resource = classLoader.getResource(resourceName); + InputStream inputStream = null; + Writer writer = new StringWriter(); + String resourceContent = EMPTY; + if (resource != null) { + try { + inputStream = resource.openStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String line = reader.readLine(); + while (line != null) { + writer.write(line); + line = reader.readLine(); + } + resourceContent = writer.toString(); + + } catch (Exception e) { + logger.log(Level.WARNING, "There was an error loading an external resource", e); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "There was an error closing input stream", e); + } + try { + writer.close(); + } catch (IOException e) { + logger.log(Level.SEVERE, "There was an error closing writer", e); + } + } + } + return resourceContent; + } +} diff --git a/receipt/src/test/resources/authentication_token_response.json b/receipt/src/test/resources/authentication_token_response.json new file mode 100644 index 000000000..e8e41bf37 --- /dev/null +++ b/receipt/src/test/resources/authentication_token_response.json @@ -0,0 +1,3 @@ +{ + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c3ItZjZlNmZjY2EtNTBmNy00ZWY1LWExYzUtNWZmMDJlMDU2MzgzIiwiaWF0IjoxNTQ5NTgwMzk0LCJleHAiOjI1NDk1ODA5OTQsImF1ZCI6InBndS03YTEyMzJlOC0xNDc5LTQzNzAtOWY1NC03ODc1ZjdiMTg2NmMiLCJpc3MiOiJwcmctY2NhODAyNWUtODVhMy0xMWU2LTg2MGEtNThhZDVlY2NlNjFkIiwicmVzdC11cmkiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVzdC92My8iLCJncmFwaHFsLXVyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9ncmFwaHFsIn0.kILSynYHbepbl4sVqENnNog09iGByfTrckHhSCjVgnuRnuspI72cx3rt0SB2V_neHwzYkD_VfhNKk9gJDOwXeQ" +} \ No newline at end of file diff --git a/ui/src/test/resources/receipt_credit_response.json b/receipt/src/test/resources/receipt_credit_response.json similarity index 100% rename from ui/src/test/resources/receipt_credit_response.json rename to receipt/src/test/resources/receipt_credit_response.json diff --git a/ui/src/test/resources/receipt_debit_response.json b/receipt/src/test/resources/receipt_debit_response.json similarity index 100% rename from ui/src/test/resources/receipt_debit_response.json rename to receipt/src/test/resources/receipt_debit_response.json diff --git a/ui/src/test/resources/receipt_list_response.json b/receipt/src/test/resources/receipt_list_response.json similarity index 100% rename from ui/src/test/resources/receipt_list_response.json rename to receipt/src/test/resources/receipt_list_response.json diff --git a/ui/src/androidTest/AndroidManifest.xml b/ui/src/androidTest/AndroidManifest.xml deleted file mode 100644 index 9b2c52c35..000000000 --- a/ui/src/androidTest/AndroidManifest.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file From 5705c8d6e42dc3adcaa76f03c686803cc47431e2 Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Tue, 11 Jun 2019 12:25:06 -0700 Subject: [PATCH 5/6] Adding test for unknown transaction type --- .../android/receipt/ListReceiptsTest.java | 32 +++++++++++++++++-- .../receipt_unknown_type_response.json | 30 +++++++++++++++++ ui/src/androidTest/AndroidManifest.xml | 9 ++++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 receipt/src/test/resources/receipt_unknown_type_response.json create mode 100644 ui/src/androidTest/AndroidManifest.xml diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java index d0a99c292..31e596bc9 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java @@ -146,7 +146,7 @@ public void testListReceipts_displayCreditTransaction() { onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); onView(withId(R.id.list_receipts)).check( - matches(atPosition(0, hasDescendant(withText("Payment"))))); + matches(atPosition(0, hasDescendant(withText(R.string.payment))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); onView(withId(R.id.list_receipts)).check( @@ -174,7 +174,7 @@ public void testListReceipts_displayDebitTransaction() { onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText(com.hyperwallet.android.receipt.R.string.debit))))); onView(withId(R.id.list_receipts)).check( - matches(atPosition(0, hasDescendant(withText("Card Load"))))); + matches(atPosition(0, hasDescendant(withText(R.string.transfer_to_prepaid_card))))); onView(withId(R.id.list_receipts)).check( matches(atPosition(0, hasDescendant(withText("- 18.05"))))); onView(withId(R.id.list_receipts)).check( @@ -184,6 +184,34 @@ public void testListReceipts_displayDebitTransaction() { onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); } + @Test + public void testListReceipts_displayUnknownTransactionType() { + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager + .getResourceContent("receipt_unknown_type_response.json")).mock(); + + // run test + mActivityTestRule.launchActivity(null); + + // assert + onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar)))) + .check(matches(withText(R.string.title_activity_receipt_list))); + onView(withId(R.id.list_receipts)).check(matches(isDisplayed())); + + onView(withId(R.id.list_receipts)) + .check(matches(atPosition(0, hasDescendant(withText("June 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, + hasDescendant(withText(com.hyperwallet.android.receipt.R.string.credit))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText(R.string.unknown_type))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("+ 25.00"))))); + onView(withId(R.id.list_receipts)).check( + matches(atPosition(0, hasDescendant(withText("June 02, 2019"))))); + onView(withId(R.id.list_receipts)).check(matches(atPosition(0, hasDescendant(withText("CAD"))))); + + onView(withId(R.id.list_receipts)).check(new RecyclerViewCountAssertion(1)); + } + @Test public void testListReceipt_userHasNoTransactions() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); diff --git a/receipt/src/test/resources/receipt_unknown_type_response.json b/receipt/src/test/resources/receipt_unknown_type_response.json new file mode 100644 index 000000000..bf856ed63 --- /dev/null +++ b/receipt/src/test/resources/receipt_unknown_type_response.json @@ -0,0 +1,30 @@ +{ + "count": 1, + "offset": 0, + "limit": 10, + "data": [ + { + "journalId": "3051581", + "type": "ICK", + "createdOn": "2019-06-02T17:09:07", + "entry": "CREDIT", + "sourceToken": "act-12345", + "destinationToken": "usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d", + "amount": "25.00", + "fee": "0.00", + "currency": "CAD", + "details": { + "clientPaymentId": "ABC1234", + "payeeName": "A Person" + } + } + ], + "links": [ + { + "params": { + "rel": "self" + }, + "href": "https://api.sandbox.hyperwallet.com/rest/v3/users/usr-fa76a738-f43d-48b9-9a7a-7048d44a5d2d/receipts?offset=0&limit=10" + } + ] +} \ No newline at end of file diff --git a/ui/src/androidTest/AndroidManifest.xml b/ui/src/androidTest/AndroidManifest.xml new file mode 100644 index 000000000..0cd133def --- /dev/null +++ b/ui/src/androidTest/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file From ef02b417f9f002a4eda49a1fdafc7b5a234e2120 Mon Sep 17 00:00:00 2001 From: Shyang Koong Date: Tue, 11 Jun 2019 12:43:34 -0700 Subject: [PATCH 6/6] Adding leak canary and ending response for receipts --- receipt/src/androidTest/AndroidManifest.xml | 9 ++++++ ...yperwalletInstrumentedTestApplication.java | 31 +++++++++++++++++++ .../android/receipt/ListReceiptsTest.java | 6 ++++ 3 files changed, 46 insertions(+) create mode 100644 receipt/src/androidTest/AndroidManifest.xml create mode 100644 receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java diff --git a/receipt/src/androidTest/AndroidManifest.xml b/receipt/src/androidTest/AndroidManifest.xml new file mode 100644 index 000000000..8495adb45 --- /dev/null +++ b/receipt/src/androidTest/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java b/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java new file mode 100644 index 000000000..dfc559d2e --- /dev/null +++ b/receipt/src/androidTest/java/com/hyperwallet/android/HyperwalletInstrumentedTestApplication.java @@ -0,0 +1,31 @@ +package com.hyperwallet.android; + + +import android.app.Application; + +import com.squareup.leakcanary.InstrumentationLeakDetector; +import com.squareup.leakcanary.LeakCanary; + +public class HyperwalletInstrumentedTestApplication extends Application { + + @Override + public void onCreate() { + + super.onCreate(); + if (LeakCanary.isInAnalyzerProcess(this)) { + // This process is dedicated to LeakCanary for heap analysis. + // You should not init your app in this process. + return; + } + installLeakCanary(); + } + + + protected void installLeakCanary() { + + InstrumentationLeakDetector.instrumentationRefWatcher(this) + .buildAndInstall(); + + } + +} \ No newline at end of file diff --git a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java index 31e596bc9..5eb430354 100644 --- a/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java +++ b/receipt/src/androidTest/java/com/hyperwallet/android/receipt/ListReceiptsTest.java @@ -72,6 +72,7 @@ public void cleanup() { public void testListReceipts_userHasMultipleTransactions() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_list_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); // run test mActivityTestRule.launchActivity(null); @@ -132,6 +133,7 @@ public void testListReceipts_userHasMultipleTransactions() { public void testListReceipts_displayCreditTransaction() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_credit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); // run test mActivityTestRule.launchActivity(null); @@ -160,6 +162,7 @@ public void testListReceipts_displayCreditTransaction() { public void testListReceipts_displayDebitTransaction() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_debit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); // run test mActivityTestRule.launchActivity(null); @@ -188,6 +191,7 @@ public void testListReceipts_displayDebitTransaction() { public void testListReceipts_displayUnknownTransactionType() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_unknown_type_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); // run test mActivityTestRule.launchActivity(null); @@ -229,6 +233,8 @@ public void testListReceipt_userHasNoTransactions() { public void testListReceipts_checkDateTextOnLocaleChange() { mMockWebServer.mockResponse().withHttpResponseCode(HTTP_OK).withBody(sResourceManager .getResourceContent("receipt_debit_response.json")).mock(); + mMockWebServer.mockResponse().withHttpResponseCode(HTTP_NO_CONTENT).withBody("").mock(); + setLocale(Locale.ITALY); // run test mActivityTestRule.launchActivity(null);