Android Espresso - 检查 RecyclerView 中是否不存在文本

问题描述 投票:0回答:2

我有代码检查

RecyclerView
中是否存在带有文本“Product”的行:

onView(withId(R.id.rv_list)).perform(scrollTo(hasDescendant(withText("Product"))));
onView(withItemText("Product")).check(matches(isDisplayed()));

public static Matcher<View> withItemText(final String itemText) {
    checkArgument(!TextUtils.isEmpty(itemText), "itemText cannot be null or empty");
    return new TypeSafeMatcher<View>() {
        @Override
        public boolean matchesSafely(View item) {
            return allOf(
                    isDescendantOfA(isAssignableFrom(RecyclerView.class)),
                    withText(itemText)).matches(item);
        }
        @Override
        public void describeTo(Description description) {
            description.appendText("is isDescendantOfA RV with text " + itemText);
        }
    };
}

如何检查

RecylerView
的所有列表中是否没有包含提供文本的行?

android android-recyclerview android-espresso
2个回答
10
投票

您可以尝试创建一个自定义匹配器来迭代

RecyclerView
项目:

public static Matcher<View> hasItem(Matcher<View> matcher) {
    return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {

        @Override public void describeTo(Description description) {
            description.appendText("has item: ");
            matcher.describeTo(description);
        }

        @Override protected boolean matchesSafely(RecyclerView view) {
            RecyclerView.Adapter adapter = view.getAdapter();
            for (int position = 0; position < adapter.getItemCount(); position++) {
                int type = adapter.getItemViewType(position);
                RecyclerView.ViewHolder holder = adapter.createViewHolder(view, type);
                adapter.onBindViewHolder(holder, position);
                if (matcher.matches(holder.itemView)) {
                    return true;
                }
            }
            return false;
        }
    };
}

如果您想检查是否没有包含特定文本的行,您可以这样做:

onView(withId(R.id.rv_list)).check(matches(not(hasItem(hasDescendant(withText("Product"))))));

0
投票

更灵活的解决方案是不将其限制为

hasItem
功能,而是通过适配器的项目提供通用步行者,以便可以使用任何可迭代匹配器。 Kotlin 示例:

@OptIn(ExperimentalStdlibApi::class)
fun recyclerChildViews(matcher: Matcher<MutableIterable<*>>): BoundedMatcher<View?, RecyclerView> =
    object : BoundedMatcher<View?, RecyclerView>(RecyclerView::class.java) {
        override fun describeTo(description: Description) {
            description.appendText("RecyclerView child views: ")
            matcher.describeTo(description)
        }

        override fun matchesSafely(recyclerView: RecyclerView): Boolean =
            matcher.matches(sequence {
                val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
                    recyclerView.adapter as RecyclerView.Adapter<RecyclerView.ViewHolder>
                for (position in 0..<adapter.itemCount) {
                    val holder = adapter.createViewHolder(recyclerView, adapter.getItemViewType(position))
                    adapter.onBindViewHolder(holder, position)
                    yield(holder.itemView)
                }
            })
    }

然后您将可以使用所有可迭代的匹配器。要使用此版本来解决原始问题,它将更改为:

onView(withId(R.id.rv_list)).check(matches(not(recyclerChildViews(hasItem(hasDescendant(withText("Product")))))))
© www.soinside.com 2019 - 2024. All rights reserved.