Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertTrue;

/**
Expand All @@ -51,6 +52,31 @@
@RunWith(AndroidJUnit4.class)
public class MainActivityHappyPathTest extends MainActivityBaseTest {

// Custom matcher that matches only the first view matching the given matcher.
public static Matcher<View> first(final Matcher<View> matcher) {
return new TypeSafeMatcher<View>() {
boolean matched = false;

@Override
public boolean matchesSafely(View view) {
if (matched) {
return false;
}
if (matcher.matches(view)) {
matched = true;
return true;
}
return false;
}

@Override
public void describeTo(Description description) {
description.appendText("first view matching: ");
matcher.describeTo(description);
}
};
}

// Custom matcher to check if a CollapsingToolbarLayout's title contains specific text
public static Matcher<View> withCollapsingToolbarTitle(final Matcher<String> textMatcher) {
return new TypeSafeMatcher<View>() {
Expand Down Expand Up @@ -368,4 +394,36 @@ public void MainActivity_ShowsTutorialOnce() throws InterruptedException {
// Put the address back.
AccountManager.Instance.setAddress(context, address);
}

@Test
public void testBookmarkToggle() {
setupMockResponses(/*isSplit=*/false, /*hasLocation=*/true);
setupMockRequestQueue();
launchMainActivity(1000);

// Tap the first bookmark icon to bookmark the issue.
onView(first(allOf(withId(R.id.bookmark_icon),
withContentDescription(R.string.bookmark_issue),
isDisplayed())))
.perform(click());

// Verify it changed to the "bookmarked" state.
onView(first(allOf(withId(R.id.bookmark_icon),
withContentDescription(R.string.remove_bookmark),
isDisplayed())))
.check(matches(isDisplayed()));

// Tap again to un-bookmark.
onView(first(allOf(withId(R.id.bookmark_icon),
withContentDescription(R.string.remove_bookmark),
isDisplayed())))
.perform(click());

// Verify it returned to the "not bookmarked" state — all icons should
// be back to "Bookmark issue" since only the first was toggled.
onView(first(allOf(withId(R.id.bookmark_icon),
withContentDescription(R.string.bookmark_issue),
isDisplayed())))
.check(matches(isDisplayed()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package org.a5calls.android.a5calls.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import org.a5calls.android.a5calls.R;

import java.util.ArrayList;
import java.util.List;

/**
* Adapter for the filter dropdown that shows hard-coded filters (All issues, Top issues, Saved)
* followed by a divider, then dynamic category/state filters.
*/
public class FilterAdapter extends BaseAdapter {
private static final int VIEW_TYPE_NORMAL = 0;
private static final int VIEW_TYPE_DIVIDER = 1;

/** Number of hard-coded filter items before the divider. */
public static final int HARD_CODED_COUNT = 3;

private final Context mContext;
private final List<String> mItems;

public FilterAdapter(Context context, List<String> items) {
mContext = context;
mItems = items;
}

@Override
public int getCount() {
if (mItems.size() > HARD_CODED_COUNT) {
return mItems.size() + 1; // +1 for the divider
}
return mItems.size();
}

@Override
public Object getItem(int position) {
if (position < HARD_CODED_COUNT) {
return mItems.get(position);
}
if (position == HARD_CODED_COUNT && mItems.size() > HARD_CODED_COUNT) {
return null; // divider
}
return mItems.get(position - 1); // offset by divider
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public int getViewTypeCount() {
return 2;
}

@Override
public int getItemViewType(int position) {
if (position == HARD_CODED_COUNT && mItems.size() > HARD_CODED_COUNT) {
return VIEW_TYPE_DIVIDER;
}
return VIEW_TYPE_NORMAL;
}

@Override
public boolean isEnabled(int position) {
return getItemViewType(position) != VIEW_TYPE_DIVIDER;
}

@Override
public boolean areAllItemsEnabled() {
return false;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (getItemViewType(position) == VIEW_TYPE_DIVIDER) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext)
.inflate(R.layout.filter_divider_item, parent, false);
}
return convertView;
}

if (convertView == null || convertView.getId() == R.id.filter_divider) {
convertView = LayoutInflater.from(mContext)
.inflate(R.layout.filter_list_item, parent, false);
}
String text = getFilterText(position);
((TextView) convertView).setText(text);
return convertView;
}

/**
* Returns the actual filter text for a given adapter position, accounting for the divider.
*/
public String getFilterText(int position) {
if (position < HARD_CODED_COUNT) {
return mItems.get(position);
}
if (position == HARD_CODED_COUNT && mItems.size() > HARD_CODED_COUNT) {
return null; // divider
}
return mItems.get(position - 1);
}

public void notifyItemsChanged() {
notifyDataSetChanged();
}
}
Loading
Loading