রিসাইক্লারভিউ আইটেমের ভিতরে ভিউ ক্লিক করতে এসপ্রেসো ব্যবহার করে


102

আমি রিসাইক্লারভিউ আইটেমের ভিতরে একটি নির্দিষ্ট ভিউ ক্লিক করতে কীভাবে এসপ্রেসো ব্যবহার করতে পারি ? আমি জানি আমি 0 পজিশনে আইটেমটি ক্লিক করে এটি ব্যবহার করতে পারি:

onView(withId(R.id.recyclerView)) .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));

তবে আমি সেই আইটেমটির ভিতরে নয় বরং সেই আইটেমটির ভিতরে একটি নির্দিষ্ট ভিউতে ক্লিক করতে হবে।

আগাম ধন্যবাদ.

- সম্পাদনা -

আরও ভালো হবে: আমি একটি আছে RecyclerView ( R.id.recycler_view) যা আইটেম নেই CardView ( R.id.card_view)। প্রতিটি কার্ডভিউয়ের ভিতরে আমার চারটি বোতাম রয়েছে (অন্যান্য জিনিসের মধ্যে) এবং আমি একটি নির্দিষ্ট বোতামে ক্লিক করতে চাই ( R.id.bt_deliver)।

আমি এসপ্রেসো ২.০ এর নতুন বৈশিষ্ট্যগুলি ব্যবহার করতে চাই তবে আমি নিশ্চিত যে এটি সম্ভব কিনা।

যদি সম্ভব না হয় তবে আমি এই জাতীয় কিছু ব্যবহার করতে চাই (টমাস কেলার কোড ব্যবহার করে):

onRecyclerItemView(R.id.card_view, ???, withId(R.id.bt_deliver)).perform(click());

তবে প্রশ্ন চিহ্নগুলিতে কী রাখবেন তা আমি জানি না।


পরীক্ষা করে দেখুন এই
Skizo-ozᴉʞS

4
হাই, দ্রুত উত্তরের জন্য ট্যাঙ্কস! :-) আমি এই প্রশ্নটি দেখেছি, তবে কীভাবে আমি চাই তা করতে পুনর্ব্যবহারযোগ্য ভিউঅ্যাকশনগুলি কীভাবে ব্যবহার করতে হয় সে সম্পর্কে কোনও সহায়তা পাই না। আমার কি পুরানো উত্তরটি ব্যবহার করা উচিত ? ধন্যবাদ
ফিলিপ রামোস

আপনি কি আপনার সমস্যার কোনও সমাধান খুঁজে পেয়েছেন?
HowieH

4
@HowieH: নং আমি ছেড়ে দিল, এবং এখন আমি Robotium ব্যবহার করছি ...
ফিলিপ রামোস

উত্তর:


139

আপনি কাস্টমাইজ ভিউ ক্রিয়াটি দিয়ে এটি করতে পারেন।

public class MyViewAction {

    public static ViewAction clickChildViewWithId(final int id) {
        return new ViewAction() {
            @Override
            public Matcher<View> getConstraints() {
                return null;
            }

            @Override
            public String getDescription() {
                return "Click on a child view with specified id.";
            }

            @Override
            public void perform(UiController uiController, View view) {
                View v = view.findViewById(id);
                v.performClick();
            }
        };
    }

}

তারপরে আপনি এটিতে ক্লিক করতে পারেন

onView(withId(R.id.rv_conference_list)).perform(
            RecyclerViewActions.actionOnItemAtPosition(0, MyViewAction.clickChildViewWithId(R.id. bt_deliver)));

4
আমি নাল চেকটি সরিয়ে ফেলব, যাতে চাইল্ড ভিউ না পাওয়া গেলে চুপচাপ কিছু না করার পরিবর্তে একটি ব্যতিক্রম ছুঁড়ে ফেলা হয়।
আলভারো গুতেরেজ পেরেজ

উত্তর করার জন্য ধন্যবাদ. তবে একটি সমস্যায় পড়েছি। অন ​​পারফর্ম () ফাংশনে, আমি যদি অনভিউ (উইথ আইডি ()) ফাংশনটি ব্যবহার করি তবে ফাংশনটি আঘাত হানে। এই আচরণের কারণ কী?
thedarkp যাত্রী

4
এস্প্রেসো নিয়ে কাজ করে: এস্প্রেসো-অবদান: ২.২.২ তবে কোনও কারণেই নয় ২.২.১ কেন? আমার কিছু নির্ভরতা রয়েছে যার কারণে আমি ২.২.২ ব্যবহার করতে পারি না।
রোজআং

4
আমি মূলত এটির সাথে একটি নালপয়েন্টার এক্সসেপশন পেয়ে যাচ্ছিলাম, সুতরাং এড়াতে আমাকে getConstraints () প্রয়োগ করতে হয়েছিল। নিম্নলিখিতগুলি আমার জন্য কাজ করেছে: পাবলিক ম্যাচার <ভিউ> getConstraints () {রিটার্ন isAignignableFrom (View.class); }
dfinn

উপরের সমাধানটি আমার পক্ষে কাজ করছে না। আমি নিম্নলিখিত ত্রুটিটি পেয়েছি: android.support.test.espresso.PerforException: 'android.support.test.espresso.contrib.RecyclerViewAtions$ActionOnItemAtPositionViewAction@fad9df' আইডিতে 'ভিউ' সম্পাদনের সময় ত্রুটি : আইডি / রিসাইক্লারভিউ '।
অ্যাডাম হুরউইৎজ

68

এখন android.support.test.espresso.contrib সহ এটি আরও সহজ হয়ে গেছে:

1) পরীক্ষা নির্ভরতা যুক্ত করুন

androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.0') {
    exclude group: 'com.android.support', module: 'appcompat'
    exclude group: 'com.android.support', module: 'support-v4'
    exclude module: 'recyclerview-v7'
}

* 3 টি মডিউল বাদ দিন, কারণ সম্ভবত আপনার এটি ইতিমধ্যে রয়েছে

2) তারপরে এমন কিছু করুন

onView(withId(R.id.recycler_grid))
            .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));

বা

onView(withId(R.id.recyclerView))
  .perform(RecyclerViewActions.actionOnItem(
            hasDescendant(withText("whatever")), click()));

বা

onView(withId(R.id.recycler_linear))
            .check(matches(hasDescendant(withText("whatever"))));

4
ধন্যবাদ, mod মডিউলগুলি জাভা.এল্যাংয়ের ফলাফলগুলিকে বাদ না দিয়ে। আমার সাথে যোগাযোগযোগ্য ক্লাসচেনজ এরর করুন।
hboy

8
এবং ক্লিক করতে কী করতে হবে আসুন তালিকার 5 ম আইটেমে একটি নির্দিষ্ট দর্শন বলুন? প্রদত্ত উদাহরণগুলিতে আমি কেবলমাত্র 5 তম আইটেমটি ক্লিক করতে দেখি বা বংশধর দর্শন সহ আইটেমটি ক্লিক করতে পারি তবে উভয়ই একসাথে নয়, বা আমি কিছু মিস করেছি?
donfuxx

4
আমার করতে হয়েছিলexclude group: 'com.android.support' exclude module: 'recyclerview-v7'
জেমশিত ইস্কেন্দরোভ

4
আপনি যখন রিসাইক্লারভিউয়ের ভিতরে চেকবক্সে ক্লিক করতে চান তখন এটি অকেজো।
ফরিদ

4
কোটলিনে actionOnItemAtPositionএকটি টাইপ পরম প্রয়োজন। সেখানে কী রাখবেন তা নিশ্চিত নয়।
জিরো ডাইভাইড

7

এখানে, আমি কীভাবে কোটলিনে সমস্যার সমাধান করেছি:

fun clickOnViewChild(viewId: Int) = object : ViewAction {
    override fun getConstraints() = null

    override fun getDescription() = "Click on a child view with specified id."

    override fun perform(uiController: UiController, view: View) = click().perform(uiController, view.findViewById<View>(viewId))
}

এবং তারপর

onView(withId(R.id.recyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(position, clickOnViewChild(R.id.viewToClickInTheRow)))

আমি E / TestRunner এর মুখোমুখি হয়েছি: java.lang. নালপয়েন্টারএক্সেপশন: নাল বস্তুর রেফারেন্সে ভার্চুয়াল পদ্ধতিতে 'অকার্যকর android.view.View.getLocationOnScreen (int [])' আহ্বান করার চেষ্টা করা হয়েছে; কোন ধারণা কেন?
sayvortana

6

পরবর্তী পদ্ধতির চেষ্টা করুন:

    onView(withRecyclerView(R.id.recyclerView)
                    .atPositionOnView(position, R.id.bt_deliver))
                    .perform(click());

    public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) {
            return new RecyclerViewMatcher(recyclerViewId);
    }

public class RecyclerViewMatcher {
    final int mRecyclerViewId;

    public RecyclerViewMatcher(int recyclerViewId) {
        this.mRecyclerViewId = recyclerViewId;
    }

    public Matcher<View> atPosition(final int position) {
        return atPositionOnView(position, -1);
    }

    public Matcher<View> atPositionOnView(final int position, final int targetViewId) {

        return new TypeSafeMatcher<View>() {
            Resources resources = null;
            View childView;

            public void describeTo(Description description) {
                int id = targetViewId == -1 ? mRecyclerViewId : targetViewId;
                String idDescription = Integer.toString(id);
                if (this.resources != null) {
                    try {
                        idDescription = this.resources.getResourceName(id);
                    } catch (Resources.NotFoundException var4) {
                        idDescription = String.format("%s (resource name not found)", id);
                    }
                }

                description.appendText("with id: " + idDescription);
            }

            public boolean matchesSafely(View view) {

                this.resources = view.getResources();

                if (childView == null) {
                    RecyclerView recyclerView =
                            (RecyclerView) view.getRootView().findViewById(mRecyclerViewId);
                    if (recyclerView != null) {

                        childView = recyclerView.findViewHolderForAdapterPosition(position).itemView;
                    }
                    else {
                        return false;
                    }
                }

                if (targetViewId == -1) {
                    return view == childView;
                } else {
                    View targetView = childView.findViewById(targetViewId);
                    return view == targetView;
                }

            }
        };
    }
}

3

আপনি করতে পারেন ক্লিক উপর 3 য় আইটেমটি এর recyclerViewমতো এই:

onView(withId(R.id.recyclerView)).perform(
                RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(2,click()))

না ভুলবেন না প্রদান ViewHolderযাতে অনুমান খেলাফ করেন না প্রকার।


4
আমি অনুপস্থিত ছিলাম <RecyclerView.ViewHolder>স্যার আপনাকে ধন্যবাদ;)
স্কিজো-ওজেস

0

উপরের সমস্ত উত্তর আমার পক্ষে কাজ করে নি তাই আমি একটি নতুন পদ্ধতি তৈরি করেছি যা অনুরোধ করা আইডির সাথে ভিউ ফেরত দেওয়ার জন্য একটি ঘরের ভিতরে সমস্ত দৃষ্টিভঙ্গি অনুসন্ধান করে। এর জন্য দুটি পদ্ধতি প্রয়োজন (একের সাথে একত্রিত হতে পারে):

fun performClickOnViewInCell(viewID: Int) = object : ViewAction {
    override fun getConstraints(): org.hamcrest.Matcher<View> = click().constraints
    override fun getDescription() = "Click on a child view with specified id."
    override fun perform(uiController: UiController, view: View) {
        val allChildViews = getAllChildrenBFS(view)
        for (child in allChildViews) {
            if (child.id == viewID) {
                child.callOnClick()
            }
        }
    }
}


private fun  getAllChildrenBFS(v: View): List<View> {
    val visited = ArrayList<View>();
    val unvisited = ArrayList<View>();
    unvisited.add(v);

    while (!unvisited.isEmpty()) {
        val child = unvisited.removeAt(0);
        visited.add(child);
        if (!(child is ViewGroup)) continue;
        val group = child
        val childCount = group.getChildCount();
        for (i in 0 until childCount) { unvisited.add(group.getChildAt(i)) }
    }

    return visited;
}

তারপরে চূড়ান্ত আপনি নিম্নলিখিতটি করে পুনর্ব্যবহারযোগ্য ভিউতে এটি ব্যবহার করতে পারেন:

onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition<RecyclerView.ViewHolder>(0, getViewFromCell(R.id.cellInnerView) {
            val requestedView = it
}))

আপনি যদি এটির সাথে অন্য কিছু করতে চান তবে ভিউটি ফিরে আসতে আপনি একটি কলব্যাক ব্যবহার করতে পারেন, বা অন্য কোনও কাজ করার জন্য এটির 3-4 টি আলাদা সংস্করণ তৈরি করতে পারেন।


0

@ ব্লেডের উত্তর আমার পক্ষে কেন কাজ করছে না তা অনুসন্ধান করার জন্য আমি বিভিন্ন পদ্ধতি চেষ্টা করে চলেছি, কেবলমাত্র বুঝতে পারি যে আমার কাছে একটি রয়েছে OnTouchListener(), আমি সেই অনুযায়ী ভিউটি সংশোধন করেছি:

fun clickTopicToWeb(id: Int): ViewAction {

        return object : ViewAction {
            override fun getDescription(): String {...}

            override fun getConstraints(): Matcher<View> {...}

            override fun perform(uiController: UiController?, view: View?) {

                view?.findViewById<View>(id)?.apply {

                    //Generalized for OnClickListeners as well
                    if(isEnabled && isClickable && !performClick()) {
                        //Define click event
                        val event: MotionEvent = MotionEvent.obtain(
                          SystemClock.uptimeMillis(),
                          SystemClock.uptimeMillis(),
                          MotionEvent.ACTION_UP,
                          view.x,
                          view.y,
                          0)

                        if(!dispatchTouchEvent(event))
                            throw Exception("Not clicking!")
                    }
                }
            }
        }
    }

0

আপনি না শুধুমাত্র আরও ক্রিয়া সমর্থন সমর্থন এই পদ্ধতির সাধারণ করতে পারেন click। এটির জন্য আমার সমাধানটি এখানে:

fun <T : View> recyclerChildAction(@IdRes id: Int, block: T.() -> Unit): ViewAction {
  return object : ViewAction {
    override fun getConstraints(): Matcher<View> {
      return any(View::class.java)
    }

    override fun getDescription(): String {
      return "Performing action on RecyclerView child item"
    }

    override fun perform(
        uiController: UiController,
        view: View
    ) {
      view.findViewById<T>(id).block()
    }
  }
 
}

এবং তারপরে EditTextআপনি এর মতো কিছু করতে পারেন:

onView(withId(R.id.yourRecyclerView))
        .perform(
            actionOnItemAtPosition<YourViewHolder>(
                0,
                recyclerChildAction<EditText>(R.id.editTextId) { setText("1000") }
            )
        )

-5

প্রথমে আপনার বোতামগুলিকে অনন্য সামগ্রী দাখিল করুন, অর্থাত "বিতরণ বোতামের সারি 5"।

<button android:contentDescription=".." />

তারপরে সারিতে স্ক্রোল করুন:

onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.scrollToPosition(5));

তারপরে কনটেন্টডেসক্রিপশনের ভিত্তিতে ভিউ নির্বাচন করুন।

onView(withContentDescription("delivery button row 5")).perform(click());

এসপ্রেসোর অনভিউ ব্যবহার এবং আপনার অ্যাপ্লিকেশনটিকে আরও অ্যাক্সেসযোগ্য করার জন্য সামগ্রী বিবরণ একটি দুর্দান্ত উপায়।


4
সামগ্রীর বিবরণটি এমনভাবে ব্যবহার করা উচিত নয় - এটি আপনার 1111 চাহিদাযুক্ত ব্যবহারকারীদের জন্য প্রযুক্তিগত বা ডিবাগ তথ্য সন্ধানের জন্য ভিউগুলির পক্ষে আরও অ্যাক্সেসযোগ্য করে তোলে না - এর সিডি সম্ভবত "অর্ডার <আইটেমের সারাংশ> এর মতো কিছু হতে হবে বোতাম "। withText("Order")খুব কার্যকর হবে এবং পরীক্ষার সময় আপনি কী অর্ডার দিচ্ছেন তা জানতে আপনার প্রয়োজন হবে না।
ataulm
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.