From 72984a68e05aa191ed152448ea88e225db8d1887 Mon Sep 17 00:00:00 2001 From: gdomingues Date: Mon, 5 Aug 2019 15:58:47 +0200 Subject: [PATCH 1/7] Separate and generalize actions for child views --- .../internal/viewaction/ChildActions.kt | 56 +++++++++++++ .../internal/viewaction/ClickChildAction.java | 80 ------------------- 2 files changed, 56 insertions(+), 80 deletions(-) create mode 100644 library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ChildActions.kt delete mode 100644 library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ClickChildAction.java diff --git a/library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ChildActions.kt b/library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ChildActions.kt new file mode 100644 index 000000000..28a5fcc65 --- /dev/null +++ b/library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ChildActions.kt @@ -0,0 +1,56 @@ +package com.schibsted.spain.barista.internal.viewaction + +import android.view.View +import androidx.annotation.IdRes +import androidx.test.espresso.PerformException +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.util.HumanReadables +import com.schibsted.spain.barista.internal.failurehandler.description +import com.schibsted.spain.barista.internal.util.ViewTreeAnalyzer +import org.hamcrest.Matcher +import org.hamcrest.Matchers.allOf + +object ChildActions { + + @JvmStatic + fun onChildWithId(@IdRes childId: Int, viewAction: ViewAction): ViewAction { + return onChildWithMatcher(withId(childId), viewAction) + } + + @JvmStatic + fun onChildWithMatcher(childMatcher: Matcher, viewAction: ViewAction): ViewAction { + return object : ViewAction { + override fun getConstraints(): Matcher { + return allOf(isDisplayed(), hasDescendant(childMatcher)) + } + + override fun getDescription(): String { + return "Perform " + viewAction.description + " on a child view " + childMatcher.description() + } + + override fun perform(uiController: UiController, view: View) { + var foundTarget = false + + for (child in ViewTreeAnalyzer.getAllChildren(view)) { + if (childMatcher.matches(child)) { + foundTarget = true + viewAction.perform(uiController, child) + break + } + } + + if (!foundTarget) { + throw PerformException.Builder() + .withActionDescription(description) + .withViewDescription(HumanReadables.describe(view)) + .withCause(IllegalArgumentException("Didn't find any view " + childMatcher.description())) + .build() + } + } + } + } +} diff --git a/library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ClickChildAction.java b/library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ClickChildAction.java deleted file mode 100644 index edb45b64e..000000000 --- a/library/src/main/java/com/schibsted/spain/barista/internal/viewaction/ClickChildAction.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.schibsted.spain.barista.internal.viewaction; - -import androidx.annotation.IdRes; -import androidx.test.espresso.PerformException; -import androidx.test.espresso.UiController; -import androidx.test.espresso.ViewAction; -import androidx.test.espresso.util.HumanReadables; -import android.view.View; -import android.widget.TextView; -import com.schibsted.spain.barista.internal.failurehandler.HelperFunctionsKt; -import com.schibsted.spain.barista.internal.util.ViewTreeAnalyzer; -import org.hamcrest.Matcher; - -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.withText; -import static org.hamcrest.Matchers.allOf; - -public class ClickChildAction { - - public static ViewAction clickChildWithId(@IdRes final int childId) { - - final Matcher childMatcher = withId(childId); - - return new ViewAction() { - @Override - public Matcher getConstraints() { - return allOf(isDisplayed(), hasDescendant(childMatcher)); - } - - @Override - public String getDescription() { - return "Click on a child view " + HelperFunctionsKt.description(childMatcher); - } - - @Override - public void perform(UiController uiController, View view) { - View child = view.findViewById(childId); - if (child != null) { - child.performClick(); - } else { - throw new PerformException.Builder() - .withActionDescription(getDescription()) - .withViewDescription(HumanReadables.describe(view)) - .withCause(new IllegalArgumentException("Didn't find any view " + HelperFunctionsKt.description(childMatcher))) - .build(); - } - } - }; - } - - public static ViewAction clickChildWithText(final String text) { - return new ViewAction() { - @Override - public Matcher getConstraints() { - return allOf(isDisplayed(), hasDescendant(withText(text))); - } - - @Override - public String getDescription() { - return "Click on a child View with specified text"; - } - - @Override - public void perform(UiController uiController, View view) { - for (View child : ViewTreeAnalyzer.getAllChildren(view)) { - if (child instanceof TextView) { - TextView textView = (TextView) child; - String label = textView.getText().toString(); - if (text.equalsIgnoreCase(label)) { - textView.performClick(); - return; - } - } - } - } - }; - } -} \ No newline at end of file From 9aa19dc409fe465c4e778a01024ec17a61a5d9d2 Mon Sep 17 00:00:00 2001 From: gdomingues Date: Mon, 5 Aug 2019 16:00:16 +0200 Subject: [PATCH 2/7] Add method that allow custom actions on list items child --- .../barista/interaction/BaristaListInteractions.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/com/schibsted/spain/barista/interaction/BaristaListInteractions.kt b/library/src/main/java/com/schibsted/spain/barista/interaction/BaristaListInteractions.kt index 71b045a3c..f4037f114 100644 --- a/library/src/main/java/com/schibsted/spain/barista/interaction/BaristaListInteractions.kt +++ b/library/src/main/java/com/schibsted/spain/barista/interaction/BaristaListInteractions.kt @@ -8,6 +8,7 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.FailureHandler import androidx.test.espresso.NoMatchingViewException import androidx.test.espresso.ViewAction +import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.scrollTo import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition @@ -22,7 +23,7 @@ import android.widget.AbsListView import com.schibsted.spain.barista.internal.failurehandler.SpyFailureHandler import com.schibsted.spain.barista.internal.failurehandler.description import com.schibsted.spain.barista.internal.failurehandler.withFailureHandler -import com.schibsted.spain.barista.internal.viewaction.ClickChildAction.clickChildWithId +import com.schibsted.spain.barista.internal.viewaction.ChildActions.onChildWithId import com.schibsted.spain.barista.internal.viewaction.PerformClickAction.clickUsingPerformClick import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.anyOf @@ -52,9 +53,15 @@ object BaristaListInteractions { @JvmStatic @JvmOverloads fun clickListItemChild(@IdRes id: Int? = null, position: Int, @IdRes childId: Int) { + doOnListItemChild(id, position, childId, click()) + } + + @JvmStatic + @JvmOverloads + fun doOnListItemChild(@IdRes id: Int? = null, position: Int, @IdRes childId: Int, viewAction: ViewAction) { performMagicAction(id, position, - recyclerAction = actionOnItemAtPosition(position, clickChildWithId(childId)), - listViewAction = clickChildWithId(childId) + recyclerAction = actionOnItemAtPosition(position, onChildWithId(childId, viewAction)), + listViewAction = onChildWithId(childId, viewAction) ) } From 8e1ef8147c0a8cf262331eaabf3e4dfc98aa77dd Mon Sep 17 00:00:00 2001 From: gdomingues Date: Mon, 5 Aug 2019 16:00:52 +0200 Subject: [PATCH 3/7] Add EditText to list item in order to test custom actions --- sample/src/main/res/layout/row_with_buttons.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sample/src/main/res/layout/row_with_buttons.xml b/sample/src/main/res/layout/row_with_buttons.xml index c686ac8d1..59f73dc2b 100644 --- a/sample/src/main/res/layout/row_with_buttons.xml +++ b/sample/src/main/res/layout/row_with_buttons.xml @@ -37,4 +37,10 @@ /> + + From f40c5c171d4e2e82a99b0d0b990528d30a43333a Mon Sep 17 00:00:00 2001 From: gdomingues Date: Mon, 5 Aug 2019 16:02:27 +0200 Subject: [PATCH 4/7] Add TextView to hold typed text that will be asserted on tests --- sample/src/main/res/layout/activity_lists.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sample/src/main/res/layout/activity_lists.xml b/sample/src/main/res/layout/activity_lists.xml index 20f74f0b7..66e2dc0f6 100644 --- a/sample/src/main/res/layout/activity_lists.xml +++ b/sample/src/main/res/layout/activity_lists.xml @@ -11,6 +11,12 @@ android:layout_height="wrap_content" /> + + Date: Mon, 5 Aug 2019 16:03:26 +0200 Subject: [PATCH 5/7] Set typed text to result field whenever EditText content changes --- .../spain/barista/sample/ListsActivity.java | 30 +++++++++++++++++-- .../barista/sample/TextListViewAdapter.java | 12 +++++++- .../sample/TextRecyclerViewAdapter.java | 17 +++++++++-- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/sample/src/main/java/com/schibsted/spain/barista/sample/ListsActivity.java b/sample/src/main/java/com/schibsted/spain/barista/sample/ListsActivity.java index 7af4792d8..72ef5a66c 100644 --- a/sample/src/main/java/com/schibsted/spain/barista/sample/ListsActivity.java +++ b/sample/src/main/java/com/schibsted/spain/barista/sample/ListsActivity.java @@ -6,6 +6,8 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import android.text.Editable; +import android.text.TextWatcher; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -15,6 +17,8 @@ import android.widget.ListView; import android.widget.TextView; +import org.jetbrains.annotations.NotNull; + /** * This Activity helps testing a variety of scenarios with different ListView and RecyclerView. * We can dynamically add ListViews or RecyclerViews with intent parameters. @@ -61,6 +65,7 @@ public static IntentBuilder buildIntent() { private LinearLayout listsContainer; private TextView clickedResult; + private TextView typedResult; @Override protected void onCreate(Bundle savedInstanceState) { @@ -68,6 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_lists); listsContainer = (LinearLayout) findViewById(R.id.multi_list_container); clickedResult = (TextView) findViewById(R.id.clicked_text_result); + typedResult = (TextView) findViewById(R.id.typed_text_result); for (int id : getIntent().getIntArrayExtra(EXTRA_SIMPLE_LISTS)) { addSimpleListView(id); @@ -104,7 +110,7 @@ public void onItemClick(AdapterView parent, View view, int position, long id) private void addComplexListView(int id) { ListView listView = new ListView(this); listView.setId(id); - listView.setAdapter(new TextListViewAdapter(this, FRUITS, clickedResult)); + listView.setAdapter(new TextListViewAdapter(this, FRUITS, clickedResult, createTypedResultTextWatcher())); addList(listView); } @@ -115,7 +121,7 @@ private void addRecyclerView(int id) { LinearLayoutManager mLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(mLayoutManager); - recyclerView.setAdapter(new TextRecyclerViewAdapter(FRUITS, clickedResult)); + recyclerView.setAdapter(new TextRecyclerViewAdapter(FRUITS, clickedResult, createTypedResultTextWatcher())); addList(recyclerView); } @@ -135,7 +141,7 @@ public void onItemClick(AdapterView parent, View view, int position, long id) private void addComplexGridView(int id) { GridView gridView = new GridView(this); gridView.setId(id); - gridView.setAdapter(new TextListViewAdapter(this, FRUITS, clickedResult)); + gridView.setAdapter(new TextListViewAdapter(this, FRUITS, clickedResult, createTypedResultTextWatcher())); addList(gridView); } @@ -148,6 +154,24 @@ private void addList(View listView) { )); } + @NotNull + private TextWatcher createTypedResultTextWatcher() { + return new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + typedResult.setText(s); + } + }; + } + public static class IntentBuilder { private int[] simpleListViewIds = {}; private int[] complexListViewIds = {}; diff --git a/sample/src/main/java/com/schibsted/spain/barista/sample/TextListViewAdapter.java b/sample/src/main/java/com/schibsted/spain/barista/sample/TextListViewAdapter.java index 1d9184601..3440d4a23 100644 --- a/sample/src/main/java/com/schibsted/spain/barista/sample/TextListViewAdapter.java +++ b/sample/src/main/java/com/schibsted/spain/barista/sample/TextListViewAdapter.java @@ -2,21 +2,25 @@ import android.app.Activity; import android.content.Context; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.EditText; import android.widget.TextView; public class TextListViewAdapter extends BaseAdapter { private Activity activity; private String[] items; private final TextView clickedResult; + private final TextWatcher textWatcher; - TextListViewAdapter(Activity activity, String[] items, TextView clickedResult) { + TextListViewAdapter(Activity activity, String[] items, TextView clickedResult, TextWatcher textWatcher) { this.activity = activity; this.items = items.clone(); this.clickedResult = clickedResult; + this.textWatcher = textWatcher; } @Override @@ -46,6 +50,8 @@ public View getView(final int position, View convertView, ViewGroup parent) { TextView textView = (TextView) rowView.findViewById(R.id.textview); View yesButton = rowView.findViewById(R.id.yes); View noButton = rowView.findViewById(R.id.no); + EditText editText = rowView.findViewById(R.id.edittext); + textView.setText(items[position]); rowView.setOnClickListener(new View.OnClickListener() { @@ -67,6 +73,10 @@ public void onClick(View view) { } }); + // Avoiding adding TextWatcher multiple times + editText.removeTextChangedListener(textWatcher); + editText.addTextChangedListener(textWatcher); + return rowView; } } diff --git a/sample/src/main/java/com/schibsted/spain/barista/sample/TextRecyclerViewAdapter.java b/sample/src/main/java/com/schibsted/spain/barista/sample/TextRecyclerViewAdapter.java index 41b37165f..de066dbbf 100644 --- a/sample/src/main/java/com/schibsted/spain/barista/sample/TextRecyclerViewAdapter.java +++ b/sample/src/main/java/com/schibsted/spain/barista/sample/TextRecyclerViewAdapter.java @@ -1,9 +1,11 @@ package com.schibsted.spain.barista.sample; import androidx.recyclerview.widget.RecyclerView; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.EditText; import android.widget.TextView; import static com.schibsted.spain.barista.sample.ListsActivity.getRecyclerViewTextAt; @@ -11,10 +13,12 @@ public class TextRecyclerViewAdapter extends RecyclerView.Adapter { private final String[] items; private final TextView clickedResult; + private final TextWatcher textWatcher; - TextRecyclerViewAdapter(String[] items, TextView clickedResult) { + TextRecyclerViewAdapter(String[] items, TextView clickedResult, TextWatcher textWatcher) { this.items = items.clone(); this.clickedResult = clickedResult; + this.textWatcher = textWatcher; } public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @@ -22,7 +26,8 @@ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { TextView textView = (TextView) root.findViewById(R.id.textview); View yesButton = root.findViewById(R.id.yes); View noButton = root.findViewById(R.id.no); - return new ViewHolder(root, textView, yesButton, noButton); + EditText editText = root.findViewById(R.id.edittext); + return new ViewHolder(root, textView, yesButton, noButton, editText, textWatcher); } public void onBindViewHolder(final ViewHolder holder, final int position) { @@ -55,12 +60,18 @@ static class ViewHolder extends RecyclerView.ViewHolder { TextView textView; View yesButton; View noButton; + EditText editText; - ViewHolder(View root, TextView textView, View yesButton, View noButton) { + ViewHolder(View root, TextView textView, View yesButton, View noButton, EditText editText, TextWatcher textWatcher) { super(root); this.textView = textView; this.yesButton = yesButton; this.noButton = noButton; + this.editText = editText; + + // Avoiding adding TextWatcher multiple times + this.editText.removeTextChangedListener(textWatcher); + this.editText.addTextChangedListener(textWatcher); } } } From f20c9d7a9468bc1f292617916cc2072a277bfa95 Mon Sep 17 00:00:00 2001 From: gdomingues Date: Mon, 5 Aug 2019 16:05:33 +0200 Subject: [PATCH 6/7] Add tests for custom actions on list item child --- ...hildClickTest.java => ListsChildTest.java} | 68 ++++++++++++++++--- 1 file changed, 58 insertions(+), 10 deletions(-) rename sample/src/androidTest/java/com/schibsted/spain/barista/sample/{ListsChildClickTest.java => ListsChildTest.java} (66%) diff --git a/sample/src/androidTest/java/com/schibsted/spain/barista/sample/ListsChildClickTest.java b/sample/src/androidTest/java/com/schibsted/spain/barista/sample/ListsChildTest.java similarity index 66% rename from sample/src/androidTest/java/com/schibsted/spain/barista/sample/ListsChildClickTest.java rename to sample/src/androidTest/java/com/schibsted/spain/barista/sample/ListsChildTest.java index dd8afba9a..421da2028 100644 --- a/sample/src/androidTest/java/com/schibsted/spain/barista/sample/ListsChildClickTest.java +++ b/sample/src/androidTest/java/com/schibsted/spain/barista/sample/ListsChildTest.java @@ -11,16 +11,19 @@ import org.junit.runner.RunWith; import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.replaceText; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.schibsted.spain.barista.interaction.BaristaKeyboardInteractions.closeKeyboard; import static com.schibsted.spain.barista.interaction.BaristaListInteractions.clickListItemChild; +import static com.schibsted.spain.barista.interaction.BaristaListInteractions.doOnListItemChild; import static com.schibsted.spain.barista.sample.ListsActivity.IntentBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @RunWith(AndroidJUnit4.class) -public class ListsChildClickTest { +public class ListsChildTest { @Rule public ActivityTestRule activity = new ActivityTestRule<>(ListsActivity.class, true, false); @@ -36,7 +39,7 @@ public void clickRecyclerItemChild() { clickListItemChild(20, R.id.yes); - assertResult("yes"); + assertClickResult("yes"); spyFailureHandlerRule.assertNoEspressoFailures(); } @@ -48,7 +51,7 @@ public void clickListViewItemChild() { clickListItemChild(20, R.id.yes); - assertResult("yes"); + assertClickResult("yes"); spyFailureHandlerRule.assertNoEspressoFailures(); } @@ -60,7 +63,7 @@ public void clickGridViewItemChild() { clickListItemChild(20, R.id.yes); - assertResult("yes"); + assertClickResult("yes"); spyFailureHandlerRule.assertNoEspressoFailures(); } @@ -72,7 +75,7 @@ public void clickMultipleRecyclerItemChild_byId() { clickListItemChild(R.id.recycler, 20, R.id.yes); - assertResult("yes"); + assertClickResult("yes"); spyFailureHandlerRule.assertNoEspressoFailures(); } @@ -84,7 +87,7 @@ public void clickMultipleListViewItemChild_byId() { clickListItemChild(R.id.listview, 20, R.id.yes); - assertResult("yes"); + assertClickResult("yes"); spyFailureHandlerRule.assertNoEspressoFailures(); } @@ -96,7 +99,46 @@ public void clickMultipleGridViewItemChild_byId() { clickListItemChild(R.id.gridview, 20, R.id.yes); - assertResult("yes"); + assertClickResult("yes"); + spyFailureHandlerRule.assertNoEspressoFailures(); + } + + @Test + public void actionMultipleRecyclerItemChild_byId() { + openActivity(ListsActivity.buildIntent() + .withRecyclers(R.id.recycler, R.id.recycler2) + ); + + String text = "It works"; + doOnListItemChild(R.id.recycler, 20, R.id.edittext, replaceText(text)); + + assertPerformActionResult(text); + spyFailureHandlerRule.assertNoEspressoFailures(); + } + + @Test + public void actionMultipleListViewItemChild_byId() { + openActivity(ListsActivity.buildIntent() + .withComplexLists(R.id.listview, R.id.listview2) + ); + + String text = "It works"; + doOnListItemChild(R.id.listview, 20, R.id.edittext, replaceText(text)); + + assertPerformActionResult(text); + spyFailureHandlerRule.assertNoEspressoFailures(); + } + + @Test + public void actionMultipleGridViewItemChild_byId() { + openActivity(ListsActivity.buildIntent() + .withComplexGrids(R.id.gridview, R.id.gridview2) + ); + + String text = "It works"; + doOnListItemChild(R.id.gridview, 20, R.id.edittext, replaceText(text)); + + assertPerformActionResult(text); spyFailureHandlerRule.assertNoEspressoFailures(); } @@ -110,7 +152,8 @@ public void fails_whenRecyclerChildNotExist() { spyFailureHandlerRule.assertEspressoFailures(1); assertThat(thrown).isInstanceOf(BaristaException.class) - .hasMessageContaining("Could not perform action (actionOnItemAtPosition performing ViewAction: Click on a child view ") + .hasMessageContaining( + "Could not perform action (actionOnItemAtPosition performing ViewAction: Perform single click on a child view with id: ") .hasMessageContaining("on item at position: 20) on RecyclerView") .hasCauseInstanceOf(PerformException.class) .hasStackTraceContaining("Didn't find any view with id"); @@ -126,16 +169,21 @@ public void fails_whenListViewChildNotExist() { spyFailureHandlerRule.assertEspressoFailures(1); assertThat(thrown).isInstanceOf(BaristaException.class) - .hasMessageContaining("Could not perform action (Click on a child view ") + .hasMessageContaining("Could not perform action (Perform single click on a child view with id: ") .hasMessageContaining("on ListView") .hasCauseInstanceOf(PerformException.class); } private void openActivity(IntentBuilder intentBuilder) { activity.launchActivity(intentBuilder.build(InstrumentationRegistry.getTargetContext())); + closeKeyboard(); } - private void assertResult(String text) { + private void assertClickResult(String text) { onView(withId(R.id.clicked_text_result)).check(matches(withText(text))); } + + private void assertPerformActionResult(String text) { + onView(withId(R.id.typed_text_result)).check(matches(withText(text))); + } } From 911675dd40f86b3caa22da6975b6c2e8d58b241a Mon Sep 17 00:00:00 2001 From: gdomingues Date: Mon, 5 Aug 2019 16:05:52 +0200 Subject: [PATCH 7/7] Add example to README file of custom action on list item child --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6c58806bc..1ac1ba324 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ clearText(R.id.edittext) ```java clickListItem(R.id.list, 4); clickListItemChild(R.id.list, 3, R.id.row_button); +doOnListItemChild(R.id.list, 5, R.id.edittext, replaceText("Yet another great text")); scrollListToPosition(R.id.list, 4); assertListItemCount(R.id.listId, 5) assertListNotEmpty(R.id.listId)