Skip to content

Commit

Permalink
Merge branch 'main' into tags-filter
Browse files Browse the repository at this point in the history
  • Loading branch information
jdrco committed Dec 1, 2023
2 parents e70f618 + c745eab commit dc66ff3
Show file tree
Hide file tree
Showing 23 changed files with 581 additions and 402 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
import static androidx.test.espresso.matcher.ViewMatchers.hasChildCount;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static com.example.househomey.testUtils.TestHelpers.enterText;
import static com.example.househomey.testUtils.TestHelpers.hasListLength;
import static com.example.househomey.testUtils.TestHelpers.mockImageBitmap;
import static com.example.househomey.testUtils.TestHelpers.mockImageUri;
import static com.example.househomey.testUtils.TestHelpers.pickDate;
import static com.example.househomey.testUtils.TestHelpers.waitFor;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anything;
Expand All @@ -27,46 +27,26 @@

import androidx.test.espresso.intent.Intents;
import androidx.test.espresso.intent.matcher.IntentMatchers;
import androidx.test.espresso.matcher.RootMatchers;

import com.example.househomey.testUtils.TestSetup;

import org.junit.Before;
import org.junit.Test;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class AddItemFragmentTest extends TestSetup {
@Before
public void navigateToAddItemFragment() {
onView(withId(R.id.action_add)).perform(click());
}

public String selectFirstDayOfMonth() {
onView(withId(R.id.add_item_date)).perform(click());
// Get the first day of the month matching MaterialDatePicker content description format
LocalDate currentDate = LocalDate.now().withDayOfMonth(1);
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("EEEE, MMMM d");
String formattedDate = currentDate.format(dateFormat);
// Select the day and click confirm
onView(withContentDescription(formattedDate))
.inRoot(RootMatchers.isDialog())
.perform(click());
onView(withId(com.google.android.material.R.id.confirm_button)).perform(click());
// Return HomePage's formatted date
return currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}

@Test
public void testAddItemWithNewUser() {
// Add acquisition date
String acquisitionDate = selectFirstDayOfMonth();
// Add required description and estimated cost
String itemDescription = "Test Item";
String estimatedCost = "99.99";
String itemMake = "MyMake";
// Add required fields
enterText(R.id.add_item_description, itemDescription);
pickDate(R.id.add_item_date, "10/01/2023");
enterText(R.id.add_item_cost, estimatedCost);
// Add values to other non-required fields
enterText(R.id.add_item_make, itemMake);
Expand All @@ -87,7 +67,7 @@ public void testAddItemWithNewUser() {
.inAdapterView(withId(R.id.item_list))
.atPosition(0)
.onChildView(withId(R.id.item_date_text))
.check(matches(withText(acquisitionDate)));
.check(matches(withText("2023-10-01")));
onData(anything())
.inAdapterView(withId(R.id.item_list))
.atPosition(0)
Expand Down Expand Up @@ -126,7 +106,6 @@ public void testRoundCostTo2Decimals() {
@Test
public void testAddPhotoFromCamera() {
// Mock a result for the system's camera
Intents.init();
Intent resultData = new Intent();
resultData.putExtra("data", mockImageBitmap(mainActivity, R.raw.classic_guitar));
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
Expand All @@ -139,7 +118,6 @@ public void testAddPhotoFromCamera() {
// Click the camera option and ensure intent was fired
onView(withId(R.id.camera_button)).perform(click());
intended(hasAction(MediaStore.ACTION_IMAGE_CAPTURE));
Intents.release();

// Check that the photo was added
onView(withId(R.id.add_photo_grid)).check(matches(hasChildCount(2)));
Expand All @@ -149,7 +127,6 @@ public void testAddPhotoFromCamera() {
@Test
public void testAddPhotoFromGallery() {
// Mock a result for the system's gallery
Intents.init();
Intent resultData = new Intent();
resultData.setData(mockImageUri(R.raw.shoes));
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
Expand All @@ -162,7 +139,6 @@ public void testAddPhotoFromGallery() {
// Click the gallery option and ensure intent was fired
onView(withId(R.id.gallery_button)).perform(click());
intended(hasAction(Intent.ACTION_PICK));
Intents.release();

// Check that the photo was added
onView(withId(R.id.add_photo_grid)).check(matches(hasChildCount(2)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public void navigateToAddItemFragment() {
@Test
public void testSetSerialNumber() {
// Mock a result for the system's gallery
Intents.init();
Intent resultData = new Intent();
resultData.setData(mockImageUri(R.raw.barcode_test));
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
Expand All @@ -46,7 +45,6 @@ public void testSetSerialNumber() {
// Click the gallery option and ensure intent was fired
onView(withId(R.id.gallery_button)).perform(click());
intended(hasAction(Intent.ACTION_PICK));
Intents.release();

waitFor(() -> onView(withText("Serial Number")).perform(click()));

Expand All @@ -57,7 +55,6 @@ public void testSetSerialNumber() {
@Test
public void testSetDescription() {
// Mock a result for the system's gallery
Intents.init();
Intent resultData = new Intent();
resultData.setData(mockImageUri(R.raw.barcode_test));
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
Expand All @@ -70,7 +67,6 @@ public void testSetDescription() {
// Click the gallery option and ensure intent was fired
onView(withId(R.id.gallery_button)).perform(click());
intended(hasAction(Intent.ACTION_PICK));
Intents.release();

waitFor(() -> onView(withText("Description")).perform(click()));

Expand All @@ -81,7 +77,6 @@ public void testSetDescription() {
@Test
public void testQRCodeScan() {
// Mock a result for the system's gallery
Intents.init();
Intent resultData = new Intent();
resultData.setData(mockImageUri(R.raw.househomey_qrcode));
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
Expand All @@ -94,7 +89,6 @@ public void testQRCodeScan() {
// Click the gallery option and ensure intent was fired
onView(withId(R.id.gallery_button)).perform(click());
intended(hasAction(Intent.ACTION_PICK));
Intents.release();

waitFor(() -> onView(withText("YES")).perform(click()));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,46 @@
package com.example.househomey;

import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static com.example.househomey.testUtils.TestHelpers.hasListLength;
import static com.example.househomey.testUtils.TestHelpers.pickDate;
import static com.example.househomey.testUtils.TestHelpers.waitFor;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;

import com.example.househomey.testUtils.TestSetup;

import org.junit.Before;
import org.junit.Test;
import com.example.househomey.testUtils.TestSetup;

public class DateFilterFragmentTest extends TestSetup {
@Before
public void waitForItems() {
waitFor(() -> {
onView(withId(R.id.item_list)).check(matches(isDisplayed()));
});
waitFor(() -> onView(withId(R.id.item_list)).check(matches(isDisplayed())));
navigateToDateRangeFilter();
}

@Test
public void testDateFilterWithResults() {
setDateFilter(R.id.start_date_filter, "10/01/2023");
setDateFilter(R.id.end_date_filter, "10/30/2023");
pickDate(R.id.start_date_filter, "10/01/2023");
pickDate(R.id.end_date_filter, "10/30/2023");
onView(withText("APPLY")).perform(click());
waitFor(() -> hasListLength(3));
}

@Test
public void testDateFilterWithNoResults() {
setDateFilter(R.id.start_date_filter, "10/01/2001");
setDateFilter(R.id.end_date_filter, "10/01/2001");
pickDate(R.id.start_date_filter, "10/01/2001");
pickDate(R.id.end_date_filter, "10/01/2001");
onView(withText("APPLY")).perform(click());
waitFor(() -> hasListLength(0));
}

@Test
public void testDateFilterWithOneDateFilled() {
setDateFilter(R.id.start_date_filter, "10/01/2023");
pickDate(R.id.start_date_filter, "10/01/2023");
onView(withText("APPLY")).perform(click());
waitFor(() -> hasListLength(4));
}
Expand All @@ -63,52 +54,4 @@ public void navigateToDateRangeFilter() {
onView(withText("Date Range")).perform(click());
}

/**
* Sets a date filter for a specified view element using Espresso.
*
* @param id The resource ID of the view element for which the date filter is being set.
* @param date The date string to be set in the date filter.
* This method clicks on the specified view element, switches to text input mode,
* enters the provided date, and confirms the date selection by clicking "OK".
*/
private void setDateFilter(int id, String date) {
onView(withId(id)).perform(click());
onView(withContentDescription("Switch to text input mode")).perform(click());
onView(
Matchers.allOf(childAtPosition(
childAtPosition(
withId(com.google.android.material.R.id.mtrl_picker_text_input_date),
0),
0),
isDisplayed())).perform(replaceText(date), closeSoftKeyboard());

onView(withText("OK")).perform(click());
}

/**
* Custom Matcher for locating a child {@link View} at a specific position within a parent
* {@link ViewGroup}.
*
* @param parentMatcher The {@link Matcher<View>} used to match the parent {@link View} or {@link ViewGroup}.
* @param position The position of the child {@link View} within the parent.
* @return A {@link Matcher<View>} instance for finding a child {@link View} at the specified position.
*/
Matcher<View> childAtPosition(
final Matcher<View> parentMatcher, final int position) {

return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("Child at position " + position + " in parent ");
parentMatcher.describeTo(description);
}

@Override
public boolean matchesSafely(View view) {
ViewParent parent = view.getParent();
return parent instanceof ViewGroup && parentMatcher.matches(parent)
&& view.equals(((ViewGroup) parent).getChildAt(position));
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public void navigateToAddItemFragment() {
@Test
public void testScanPhoto() {
// Mock a result for the system's gallery
Intents.init();
Intent resultData = new Intent();
resultData.setData(mockImageUri(R.raw.serial_num));
Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
Expand All @@ -49,7 +48,6 @@ public void testScanPhoto() {
// Click the gallery option and ensure intent was fired
onView(withId(R.id.gallery_button)).perform(click());
intended(hasAction(Intent.ACTION_PICK));
Intents.release();

waitFor(() -> onView(withText("YES")).perform(click()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,35 @@

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.clearText;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.pressImeActionButton;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.action.ViewActions.typeText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import androidx.annotation.IdRes;

import com.example.househomey.R;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;

/*
* Helper methods for Espresso testing in Android applications.
*
Expand Down Expand Up @@ -97,4 +109,46 @@ public static Bitmap mockImageBitmap(Activity activity, int resourceId) {
public static Uri mockImageUri(int resourceId) {
return Uri.parse("android.resource://com.example.househomey/" + resourceId);
}

/*
* Sets the Material DatePicker date for a specified date text input.
* Uses text input mode of the DatePicker.
*
* @param id The resource ID of the view element for which the date is being set.
* @param date The date string to be set.
*/
public static void pickDate(int id, String date) {
onView(withId(id)).perform(click());
onView(withContentDescription("Switch to text input mode")).perform(click());
onView(Matchers.allOf(childAtPosition(childAtPosition(
withId(com.google.android.material.R.id.mtrl_picker_text_input_date), 0), 0),
isDisplayed())).perform(replaceText(date), closeSoftKeyboard());
onView(withText("OK")).perform(click());
}

/*
* Custom Matcher for locating a child at a specific position within a parent
*
* @param parentMatcher The Matcher<View> used to match the parent View or ViewGroup
* @param position The position of the child View within the parent.
* @return A Matcher<View> instance for finding a child View at the specified position.
*/
public static Matcher<View> childAtPosition(
final Matcher<View> parentMatcher, final int position) {

return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("Child at position " + position + " in parent ");
parentMatcher.describeTo(description);
}

@Override
public boolean matchesSafely(View view) {
ViewParent parent = view.getParent();
return parent instanceof ViewGroup && parentMatcher.matches(parent)
&& view.equals(((ViewGroup) parent).getChildAt(position));
}
};
}
}
Loading

0 comments on commit dc66ff3

Please sign in to comment.