Best Appium-espresso-driver code snippet using android.support.test.espresso.matcher.ViewMatchers.hasSibling
TasksScreenTest.kt
Source:TasksScreenTest.kt  
...23import android.support.test.espresso.action.ViewActions.replaceText24import android.support.test.espresso.action.ViewActions.typeText25import android.support.test.espresso.assertion.ViewAssertions.doesNotExist26import android.support.test.espresso.assertion.ViewAssertions.matches27import android.support.test.espresso.matcher.ViewMatchers.hasSibling28import android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom29import android.support.test.espresso.matcher.ViewMatchers.isChecked30import android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA31import android.support.test.espresso.matcher.ViewMatchers.isDisplayed32import android.support.test.espresso.matcher.ViewMatchers.withContentDescription33import android.support.test.espresso.matcher.ViewMatchers.withId34import android.support.test.espresso.matcher.ViewMatchers.withText35import android.support.test.filters.LargeTest36import android.support.test.filters.SdkSuppress37import android.support.test.rule.ActivityTestRule38import android.support.test.runner.AndroidJUnit439import android.view.View40import android.widget.ListView41import com.example.android.architecture.blueprints.todoapp.Injection42import com.example.android.architecture.blueprints.todoapp.R43import com.example.android.architecture.blueprints.todoapp.ViewModelFactory44import com.example.android.architecture.blueprints.todoapp.currentActivity45import com.example.android.architecture.blueprints.todoapp.getToolbarNavigationContentDescription46import com.example.android.architecture.blueprints.todoapp.rotateOrientation47import com.google.common.base.Preconditions.checkArgument48import org.hamcrest.Description49import org.hamcrest.Matcher50import org.hamcrest.Matchers.allOf51import org.hamcrest.TypeSafeMatcher52import org.hamcrest.core.IsNot.not53import org.junit.Before54import org.junit.Rule55import org.junit.Test56import org.junit.runner.RunWith57/**58 * Tests for the tasks screen, the main screen which contains a list of all tasks.59 */60@RunWith(AndroidJUnit4::class) @LargeTest class TasksScreenTest {61    private val TITLE1 = "TITLE1"62    private val TITLE2 = "TITLE2"63    private val DESCRIPTION = "DESCR"64    /**65     * [ActivityTestRule] is a JUnit [@Rule][Rule] to launch your activity under test.66     *67     *68     * Rules are interceptors which are executed for each test method and are important building69     * blocks of Junit tests.70     */71    @Rule @JvmField var tasksActivityTestRule =72            ActivityTestRule<TasksActivity>(TasksActivity::class.java)73    @Before fun resetState() {74        ViewModelFactory.destroyInstance()75        Injection.provideTasksRepository(InstrumentationRegistry.getTargetContext())76                .deleteAllTasks()77    }78    private val toolbarNavigationContentDescription: String79        get() = tasksActivityTestRule.activity.getToolbarNavigationContentDescription(R.id.toolbar)80    /**81     * A custom [Matcher] which matches an item in a [ListView] by its text.82     *83     *84     * View constraint: View must be a child of a [ListView]85     *86     * @param itemText the text to match87     *88     * @return Matcher that matches text in the given view89     */90    private fun withItemText(itemText: String): Matcher<View> {91        checkArgument(itemText.isNotEmpty(), "itemText cannot be null or empty")92        return object : TypeSafeMatcher<View>() {93            override fun matchesSafely(item: View) = allOf(94                    isDescendantOfA(isAssignableFrom(ListView::class.java)),95                    withText(itemText)96            ).matches(item)97            override fun describeTo(description: Description) {98                description.appendText("is isDescendantOfA LV with text " + itemText)99            }100        }101    }102    @Test fun clickAddTaskButton_opensAddTaskUi() {103        // Click on the add task button104        onView(withId(R.id.fab_add_task)).perform(click())105        // Check if the add task screen is displayed106        onView(withId(R.id.add_task_title)).check(matches(isDisplayed()))107    }108    @Test fun editTask() {109        // First add a task110        createTask(TITLE1, DESCRIPTION)111        // Click on the task on the list112        onView(withText(TITLE1)).perform(click())113        // Click on the edit task button114        onView(withId(R.id.fab_edit_task)).perform(click())115        val editTaskTitle = TITLE2116        val editTaskDescription = "New Description"117        // Edit task title and description118        onView(withId(R.id.add_task_title))119                .perform(replaceText(editTaskTitle), closeSoftKeyboard()) // Type new task title120        onView(withId(R.id.add_task_description)).perform(replaceText(editTaskDescription),121                closeSoftKeyboard()) // Type new task description and close the keyboard122        // Save the task123        onView(withId(R.id.fab_edit_task_done)).perform(click())124        // Verify task is displayed on screen in the task list.125        onView(withItemText(editTaskTitle)).check(matches(isDisplayed()))126        // Verify previous task is not displayed127        onView(withItemText(TITLE1)).check(doesNotExist())128    }129    @Test fun addTaskToTasksList() {130        createTask(TITLE1, DESCRIPTION)131        // Verify task is displayed on screen132        onView(withItemText(TITLE1)).check(matches(isDisplayed()))133    }134    @Test fun markTaskAsComplete() {135        viewAllTasks()136        // Add active task137        createTask(TITLE1, DESCRIPTION)138        // Mark the task as complete139        clickCheckBoxForTask(TITLE1)140        // Verify task is shown as complete141        viewAllTasks()142        onView(withItemText(TITLE1)).check(matches(isDisplayed()))143        viewActiveTasks()144        onView(withItemText(TITLE1)).check(matches(not(isDisplayed())))145        viewCompletedTasks()146        onView(withItemText(TITLE1)).check(matches(isDisplayed()))147    }148    @Test fun markTaskAsActive() {149        viewAllTasks()150        // Add completed task151        createTask(TITLE1, DESCRIPTION)152        clickCheckBoxForTask(TITLE1)153        // Mark the task as active154        clickCheckBoxForTask(TITLE1)155        // Verify task is shown as active156        viewAllTasks()157        onView(withItemText(TITLE1)).check(matches(isDisplayed()))158        viewActiveTasks()159        onView(withItemText(TITLE1)).check(matches(isDisplayed()))160        viewCompletedTasks()161        onView(withItemText(TITLE1)).check(matches(not(isDisplayed())))162    }163    @Test fun showAllTasks() {164        // Add 2 active tasks165        createTask(TITLE1, DESCRIPTION)166        createTask(TITLE2, DESCRIPTION)167        //Verify that all our tasks are shown168        viewAllTasks()169        onView(withItemText(TITLE1)).check(matches(isDisplayed()))170        onView(withItemText(TITLE2)).check(matches(isDisplayed()))171    }172    @Test fun showActiveTasks() {173        // Add 2 active tasks174        createTask(TITLE1, DESCRIPTION)175        createTask(TITLE2, DESCRIPTION)176        //Verify that all our tasks are shown177        viewActiveTasks()178        onView(withItemText(TITLE1)).check(matches(isDisplayed()))179        onView(withItemText(TITLE2)).check(matches(isDisplayed()))180    }181    @Test fun showCompletedTasks() {182        // Add 2 completed tasks183        createTask(TITLE1, DESCRIPTION)184        clickCheckBoxForTask(TITLE1)185        createTask(TITLE2, DESCRIPTION)186        clickCheckBoxForTask(TITLE2)187        // Verify that all our tasks are shown188        viewCompletedTasks()189        onView(withItemText(TITLE1)).check(matches(isDisplayed()))190        onView(withItemText(TITLE2)).check(matches(isDisplayed()))191    }192    @Test fun clearCompletedTasks() {193        viewAllTasks()194        // Add 2 complete tasks195        createTask(TITLE1, DESCRIPTION)196        clickCheckBoxForTask(TITLE1)197        createTask(TITLE2, DESCRIPTION)198        clickCheckBoxForTask(TITLE2)199        // Click clear completed in menu200        openActionBarOverflowOrOptionsMenu(getTargetContext())201        onView(withText(R.string.menu_clear)).perform(click())202        //Verify that completed tasks are not shown203        onView(withItemText(TITLE1)).check(matches(not(isDisplayed())))204        onView(withItemText(TITLE2)).check(matches(not(isDisplayed())))205    }206    @Test fun createOneTask_deleteTask() {207        viewAllTasks()208        // Add active task209        createTask(TITLE1, DESCRIPTION)210        // Open it in details view211        onView(withText(TITLE1)).perform(click())212        // Click delete task in menu213        onView(withId(R.id.menu_delete)).perform(click())214        // Verify it was deleted215        viewAllTasks()216        onView(withText(TITLE1)).check(matches(not(isDisplayed())))217    }218    @Test fun createTwoTasks_deleteOneTask() {219        // Add 2 active tasks220        createTask(TITLE1, DESCRIPTION)221        createTask(TITLE2, DESCRIPTION)222        // Open the second task in details view223        onView(withText(TITLE2)).perform(click())224        // Click delete task in menu225        onView(withId(R.id.menu_delete)).perform(click())226        // Verify only one task was deleted227        viewAllTasks()228        onView(withText(TITLE1)).check(matches(isDisplayed()))229        onView(withText(TITLE2)).check(doesNotExist())230    }231    @Test fun markTaskAsCompleteOnDetailScreen_taskIsCompleteInList() {232        viewAllTasks()233        // Add 1 active task234        createTask(TITLE1, DESCRIPTION)235        // Click on the task on the list236        onView(withText(TITLE1)).perform(click())237        // Click on the checkbox in task details screen238        onView(withId(R.id.task_detail_complete)).perform(click())239        // Click on the navigation up button to go back to the list240        onView(withContentDescription(toolbarNavigationContentDescription)).perform(click())241        // Check that the task is marked as completed242        onView(allOf(withId(R.id.complete),243                hasSibling(withText(TITLE1)))).check(matches(isChecked()))244    }245    @Test fun markTaskAsActiveOnDetailScreen_taskIsActiveInList() {246        viewAllTasks()247        // Add 1 completed task248        createTask(TITLE1, DESCRIPTION)249        clickCheckBoxForTask(TITLE1)250        // Click on the task on the list251        onView(withText(TITLE1)).perform(click())252        // Click on the checkbox in task details screen253        onView(withId(R.id.task_detail_complete)).perform(click())254        // Click on the navigation up button to go back to the list255        onView(withContentDescription(toolbarNavigationContentDescription)).perform(click())256        // Check that the task is marked as active257        onView(allOf(withId(R.id.complete),258                hasSibling(withText(TITLE1)))).check(matches(not(isChecked())))259    }260    @Test fun markTaskAsAcompleteAndActiveOnDetailScreen_taskIsActiveInList() {261        viewAllTasks()262        // Add 1 active task263        createTask(TITLE1, DESCRIPTION)264        // Click on the task on the list265        onView(withText(TITLE1)).perform(click())266        // Click on the checkbox in task details screen267        onView(withId(R.id.task_detail_complete)).perform(click())268        // Click again to restore it to original state269        onView(withId(R.id.task_detail_complete)).perform(click())270        // Click on the navigation up button to go back to the list271        onView(withContentDescription(toolbarNavigationContentDescription)).perform(click())272        // Check that the task is marked as active273        onView(allOf(withId(R.id.complete),274                hasSibling(withText(TITLE1)))).check(matches(not(isChecked())))275    }276    @Test fun markTaskAsActiveAndCompleteOnDetailScreen_taskIsCompleteInList() {277        viewAllTasks()278        // Add 1 completed task279        createTask(TITLE1, DESCRIPTION)280        clickCheckBoxForTask(TITLE1)281        // Click on the task on the list282        onView(withText(TITLE1)).perform(click())283        // Click on the checkbox in task details screen284        onView(withId(R.id.task_detail_complete)).perform(click())285        // Click again to restore it to original state286        onView(withId(R.id.task_detail_complete)).perform(click())287        // Click on the navigation up button to go back to the list288        onView(withContentDescription(toolbarNavigationContentDescription)).perform(click())289        // Check that the task is marked as active290        onView(allOf(withId(R.id.complete),291                hasSibling(withText(TITLE1)))).check(matches(isChecked()))292    }293    @Test fun orientationChange_FilterActivePersists() {294        // Add a completed task295        createTask(TITLE1, DESCRIPTION)296        clickCheckBoxForTask(TITLE1)297        // when switching to active tasks298        viewActiveTasks()299        // then no tasks should appear300        onView(withText(TITLE1)).check(matches(not(isDisplayed())))301        // when rotating the screen302        tasksActivityTestRule.activity.rotateOrientation()303        // then nothing changes304        onView(withText(TITLE1)).check(doesNotExist())305    }306    @Test fun orientationChange_FilterCompletedPersists() {307        // Add a completed task308        createTask(TITLE1, DESCRIPTION)309        clickCheckBoxForTask(TITLE1)310        // when switching to completed tasks311        viewCompletedTasks()312        // the completed task should be displayed313        onView(withText(TITLE1)).check(matches(isDisplayed()))314        // when rotating the screen315        tasksActivityTestRule.activity.rotateOrientation()316        // then nothing changes317        onView(withText(TITLE1)).check(matches(isDisplayed()))318        onView(withText(R.string.label_completed)).check(matches(isDisplayed()))319    }320    // Blinking cursor after rotation breaks this in API 19321    @Test @SdkSuppress(minSdkVersion = 21) fun orientationChange_DuringEdit_ChangePersists() {322        // Add a completed task323        createTask(TITLE1, DESCRIPTION)324        // Open the task in details view325        onView(withText(TITLE1)).perform(click())326        // Click on the edit task button327        onView(withId(R.id.fab_edit_task)).perform(click())328        // Change task title (but don't save)329        onView(withId(R.id.add_task_title))330                .perform(replaceText(TITLE2), closeSoftKeyboard()) // Type new task title331        // Rotate the screen332        currentActivity.rotateOrientation()333        // Verify task title is restored334        onView(withId(R.id.add_task_title)).check(matches(withText(TITLE2)))335    }336    // Blinking cursor after rotation breaks this in API 19337    @Test @SdkSuppress(minSdkVersion = 21) fun orientationChange_DuringEdit_NoDuplicate() {338        // Add a completed task339        createTask(TITLE1, DESCRIPTION)340        // Open the task in details view341        onView(withText(TITLE1)).perform(click())342        // Click on the edit task button343        onView(withId(R.id.fab_edit_task)).perform(click())344        // Rotate the screen345        currentActivity.rotateOrientation()346        // Edit task title and description347        onView(withId(R.id.add_task_title))348                .perform(replaceText(TITLE2), closeSoftKeyboard()) // Type new task title349        onView(withId(R.id.add_task_description)).perform(replaceText(DESCRIPTION),350                closeSoftKeyboard()) // Type new task description and close the keyboard351        // Save the task352        onView(withId(R.id.fab_edit_task_done)).perform(click())353        // Verify task is displayed on screen in the task list.354        onView(withItemText(TITLE2)).check(matches(isDisplayed()))355        // Verify previous task is not displayed356        onView(withItemText(TITLE1)).check(doesNotExist())357    }358    @Test fun noTasks_AllTasksFilter_AddTaskViewVisible() {359        // Given an empty list of tasks, make sure "All tasks" filter is on360        viewAllTasks()361        // Add task View should be displayed362        onView(withId(R.id.noTasksAdd)).check(matches(isDisplayed()))363    }364    @Test fun noTasks_CompletedTasksFilter_AddTaskViewNotVisible() {365        // Given an empty list of tasks, make sure "All tasks" filter is on366        viewCompletedTasks()367        // Add task View should be displayed368        onView(withId(R.id.noTasksAdd)).check(matches(not(isDisplayed())))369    }370    @Test fun noTasks_ActiveTasksFilter_AddTaskViewNotVisible() {371        // Given an empty list of tasks, make sure "All tasks" filter is on372        viewActiveTasks()373        // Add task View should be displayed374        onView(withId(R.id.noTasksAdd)).check(matches(not(isDisplayed())))375    }376    private fun viewAllTasks() {377        onView(withId(R.id.menu_filter)).perform(click())378        onView(withText(R.string.nav_all)).perform(click())379    }380    private fun viewActiveTasks() {381        onView(withId(R.id.menu_filter)).perform(click())382        onView(withText(R.string.nav_active)).perform(click())383    }384    private fun viewCompletedTasks() {385        onView(withId(R.id.menu_filter)).perform(click())386        onView(withText(R.string.nav_completed)).perform(click())387    }388    private fun createTask(title: String, description: String) {389        // Click on the add task button390        onView(withId(R.id.fab_add_task)).perform(click())391        // Add task title and description392        onView(withId(R.id.add_task_title)).perform(typeText(title),393                closeSoftKeyboard()) // Type new task title394        onView(withId(R.id.add_task_description)).perform(typeText(description),395                closeSoftKeyboard()) // Type new task description and close the keyboard396        // Save the task397        onView(withId(R.id.fab_edit_task_done)).perform(click())398    }399    private fun clickCheckBoxForTask(title: String) {400        onView(allOf(withId(R.id.complete), hasSibling(withText(title)))).perform(click())401    }402    private fun getText(stringId: Int) =403            tasksActivityTestRule.activity.resources.getString(stringId)404}...Assertions.kt
Source:Assertions.kt  
...204     * @param function ViewBuilder that will result in sibling matcher205     *206     * @see ViewBuilder207     */208    fun hasSibling(function: ViewBuilder.() -> Unit) {209        view.check(ViewAssertions.matches(ViewMatchers210                .hasSibling(ViewBuilder().apply(function).getViewMatcher())))211    }212    /**213     * Checks if the view has not given sibling214     *215     * @param function ViewBuilder that will result in sibling matcher216     *217     * @see ViewBuilder218     */219    fun hasNotSibling(function: ViewBuilder.() -> Unit) {220        view.check(ViewAssertions.matches(Matchers.not(ViewMatchers221                .hasSibling(ViewBuilder().apply(function).getViewMatcher()))))222    }223    /**224     * Check if the view matches given matcher225     *226     * @param function ViewBuilder that will result in matcher227     *228     * @see ViewBuilder229     */230    fun matches(function: ViewBuilder.() -> Unit) {231        view.check(ViewAssertions.matches(ViewBuilder().apply(function).getViewMatcher()))232    }233    /**234     * Check if the view does not match given matcher235     *...InboxConversationPage.kt
Source:InboxConversationPage.kt  
...29import androidx.test.espresso.assertion.ViewAssertions.doesNotExist30import androidx.test.espresso.assertion.ViewAssertions.matches31import androidx.test.espresso.matcher.ViewMatchers32import androidx.test.espresso.matcher.ViewMatchers.hasChildCount33import androidx.test.espresso.matcher.ViewMatchers.hasSibling34import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom35import androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast36import androidx.test.espresso.matcher.ViewMatchers.withContentDescription37import androidx.test.espresso.matcher.ViewMatchers.withHint38import com.instructure.canvas.espresso.containsTextCaseInsensitive39import com.instructure.canvas.espresso.explicitClick40import com.instructure.canvas.espresso.scrollRecyclerView41import com.instructure.canvas.espresso.stringContainsTextCaseInsensitive42import com.instructure.canvas.espresso.withCustomConstraints43import com.instructure.espresso.assertDisplayed44import com.instructure.espresso.click45import com.instructure.espresso.page.BasePage46import com.instructure.espresso.page.onViewWithContentDescription47import com.instructure.espresso.page.onViewWithText48import com.instructure.espresso.page.waitForView49import com.instructure.espresso.page.waitForViewWithHint50import com.instructure.espresso.page.waitForViewWithText51import com.instructure.espresso.page.withId52import com.instructure.espresso.page.withText53import com.instructure.espresso.replaceText54import com.instructure.espresso.swipeUp55import com.instructure.pandautils.utils.ColorUtils56import com.instructure.pandautils.utils.ThemePrefs57import com.instructure.student.R58import org.hamcrest.CoreMatchers59import org.hamcrest.Description60import org.hamcrest.Matchers61import org.hamcrest.Matchers.allOf62import org.hamcrest.TypeSafeMatcher63class InboxConversationPage : BasePage(R.id.inboxConversationPage) {64    fun replyToMessage(message: String) {65        waitForViewWithText(R.string.reply).click()66        waitForViewWithHint(R.string.message).replaceText(message)67        onViewWithContentDescription("Send").perform(explicitClick())68        // Wait for reply to propagate, and for us to return to the email thread page69        waitForView(withId(R.id.starred)).assertDisplayed()70    }71    fun replyAllToMessage(replyMessage: String, expectedChipCount: Int) {72        onView(withId(R.id.messageOptions)).click()73        onView(withText("Reply All")).click()74        onView(withId(R.id.chipGroup)).check(matches(hasChildCount(expectedChipCount)))75        onView(withHint(R.string.message)).replaceText(replyMessage)76        onView(withContentDescription("Send")).perform(explicitClick())77        onView(allOf(withId(R.id.messageBody), withText(replyMessage))).assertDisplayed()78    }79    fun markUnread() {80        onView(withContentDescription(stringContainsTextCaseInsensitive("More options"))).click()81        onView(withText("Mark as Unread")).click()82    }83    fun archive() {84        onView(withContentDescription(stringContainsTextCaseInsensitive("More options"))).click()85        onView(withText("Archive")).click()86    }87    fun deleteConversation() {88        onView(withContentDescription(stringContainsTextCaseInsensitive("More options"))).click()89        onView(withText("Delete")).click()90        onView(allOf(isAssignableFrom(AppCompatButton::class.java), containsTextCaseInsensitive("DELETE")))91                .click() // Confirmation click92    }93    fun deleteMessage(messageBody: String) {94        val targetMatcher = allOf(95                withId(R.id.messageOptions),96                hasSibling(97                        allOf(98                                withId(R.id.messageBody),99                                withText(messageBody)100                        )101                )102        )103        onView(targetMatcher).click()104        // "Delete" might be off the page, esp. in landscape mode on small screens105        onView(isAssignableFrom(MenuPopupWindow.MenuDropDownListView::class.java)).swipeUp()106        onView(withText("Delete")).click()107        onView(allOf(isAssignableFrom(AppCompatButton::class.java), containsTextCaseInsensitive("DELETE")))108                .click() // Confirmation click109    }110    fun assertMessageDisplayed(message: String) {111        val itemMatcher = CoreMatchers.allOf(112                ViewMatchers.hasSibling(withId(R.id.attachmentContainer)),113                ViewMatchers.hasSibling(withId(R.id.headerDivider)),114                withId(R.id.messageBody),115                withText(message)116        )117        waitForView(itemMatcher).assertDisplayed()118    }119    fun assertMessageNotDisplayed(message: String) {120        onView(withText(message)).check(doesNotExist())121    }122    fun assertAttachmentDisplayed(displayName: String) {123        scrollRecyclerView(R.id.listView, withText(displayName))124        onViewWithText(displayName).check(matches(isDisplayingAtLeast(5)))125    }126    fun refresh() {127        Espresso.onView(Matchers.allOf(ViewMatchers.withId(R.id.swipeRefreshLayout), ViewMatchers.isDisplayingAtLeast(10)))...SolveQuizUtil.kt
Source:SolveQuizUtil.kt  
...26import android.support.test.espresso.action.ViewActions.click27import android.support.test.espresso.action.ViewActions.closeSoftKeyboard28import android.support.test.espresso.action.ViewActions.typeText29import android.support.test.espresso.matcher.ViewMatchers30import android.support.test.espresso.matcher.ViewMatchers.hasSibling31import android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom32import android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA33import android.support.test.espresso.matcher.ViewMatchers.withId34import android.support.test.espresso.matcher.ViewMatchers.withText35import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry36import android.support.test.runner.lifecycle.Stage37import android.text.TextUtils38import android.view.View39import android.widget.AdapterView40import android.widget.GridView41import android.widget.ListView42import android.widget.SeekBar43import com.google.samples.apps.topeka.model.quiz.AlphaPickerQuiz44import com.google.samples.apps.topeka.model.quiz.FillBlankQuiz45import com.google.samples.apps.topeka.model.quiz.FillTwoBlanksQuiz46import com.google.samples.apps.topeka.model.quiz.OptionsQuiz47import com.google.samples.apps.topeka.model.quiz.PickerQuiz48import com.google.samples.apps.topeka.model.quiz.Quiz49import com.google.samples.apps.topeka.model.quiz.QuizType50import com.google.samples.apps.topeka.model.quiz.ToggleTranslateQuiz51import com.google.samples.apps.topeka.model.quiz.TrueFalseQuiz52import org.hamcrest.Matcher53import org.hamcrest.Matchers.allOf54import org.hamcrest.Matchers.equalTo55import org.hamcrest.Matchers.instanceOf56import java.util.Arrays57/**58 * Utility for quiz solving.59 */60object SolveQuizUtil {61    /**62     * Solves a given quiz.63     * @param quiz Quiz to solve.64     */65    fun solveQuiz(quiz: Quiz<*>) {66        when (quiz.type) {67            QuizType.ALPHA_PICKER -> setAlphaPickerProgress(quiz as AlphaPickerQuiz)68            QuizType.PICKER -> setPickerProgress(quiz as PickerQuiz)69            QuizType.FILL_BLANK -> {70                val fillBlankQuiz = quiz as FillBlankQuiz71                var siblingText: String? = fillBlankQuiz.start72                if (TextUtils.isEmpty(siblingText)) {73                    siblingText = fillBlankQuiz.end74                }75                var viewId = R.id.quiz_edit_text76                if (TextUtils.isEmpty(siblingText)) {77                    siblingText = quiz.question78                    viewId = R.id.quiz_content79                }80                typeAndCloseOnView(fillBlankQuiz.answer, siblingText, viewId)81            }82            QuizType.FILL_TWO_BLANKS -> {83                val (_, answer) = quiz as FillTwoBlanksQuiz84                typeAndCloseOnView(answer[0], R.id.quiz_edit_text)85                typeAndCloseOnView(answer[1], R.id.quiz_edit_text_two)86            }87            QuizType.FOUR_QUARTER -> testOptionsQuizWithType(quiz, GridView::class.java)88            QuizType.SINGLE_SELECT, QuizType.SINGLE_SELECT_ITEM, QuizType.MULTI_SELECT ->89                testOptionsQuizWithType(quiz, ListView::class.java)90            QuizType.TOGGLE_TRANSLATE -> {91                val toggleTranslateQuiz = quiz as ToggleTranslateQuiz92                toggleTranslateQuiz.answer.forEach {93                    onData(equalTo(toggleTranslateQuiz.readableOptions[it]))94                            .inAdapterView(allOf(instanceOf<Any>(AdapterView::class.java),95                                    withId(R.id.quiz_content),96                                    hasSiblingWith(quiz.question)))97                            .perform(click())98                }99            }100            QuizType.TRUE_FALSE -> {101                val (_, answer) = quiz as TrueFalseQuiz102                onView(allOf(isDescendantOfA(hasSibling(withText(quiz.question))), withText(103                        if (answer) R.string.btn_true else R.string.btn_false)))104                        .perform(click())105            }106        }107    }108    private fun testOptionsQuizWithType(quiz: Quiz<*>, type: Class<out View>) {109        val stringOptionsQuiz = quiz as OptionsQuiz<*>110        stringOptionsQuiz.answer.forEach {111            onData(equalTo(stringOptionsQuiz.options[it]))112                    .inAdapterView(allOf(instanceOf<Any>(type),113                            withId(R.id.quiz_content),114                            hasSiblingWith(quiz.question)))115                    .perform(click())116        }117    }118    private fun setAlphaPickerProgress(quiz: AlphaPickerQuiz) {119        onView(allOf(isDescendantOfA(hasSibling(withText(quiz.question))), withId(R.id.seekbar)))120                .perform(object : ViewAction {121                    override fun getConstraints(): Matcher<View>? {122                        return ViewMatchers.isAssignableFrom(SeekBar::class.java)123                    }124                    override fun getDescription() = "Set progress on AlphaPickerQuizView"125                    override fun perform(uiController: UiController, view: View) {126                        val alphabet = Arrays.asList(*InstrumentationRegistry.getTargetContext()127                                .resources128                                .getStringArray(R.array.alphabet))129                        (view as SeekBar).progress = alphabet.indexOf(quiz.answer)130                    }131                })132    }133    private fun setPickerProgress(pickerQuiz: PickerQuiz) {134        onView(allOf(isDescendantOfA(hasSibling(withText(pickerQuiz.question))),135                withId(R.id.seekbar)))136                .perform(click())137                .perform(object : ViewAction {138                    override fun getConstraints(): Matcher<View>? {139                        return isAssignableFrom(SeekBar::class.java)140                    }141                    override fun getDescription() = "Set progress on PickerQuizView"142                    override fun perform(uiController: UiController, view: View) {143                        (view as SeekBar).progress = pickerQuiz.answer144                    }145                })146    }147    private fun typeAndCloseOnView(answer: String?, siblingText: String?, viewId: Int) {148        onView(allOf(withId(viewId), hasSiblingWith(siblingText)))149                .perform(typeText(answer), closeSoftKeyboard())150    }151    private fun typeAndCloseOnView(answer: String?, viewId: Int) {152        onView(withId(viewId)).perform(typeText(answer), closeSoftKeyboard())153    }154    private fun hasSiblingWith(text: String?): Matcher<View> {155        return hasSibling(withText(text))156    }157    fun rotate() {158        val activity = getCurrentActivity()!!159        val currentOrientation = activity.resources.configuration.orientation160        if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) rotateToPortrait(activity)161        else rotateToLandscape(activity)162    }163    private fun rotateToLandscape(activity: Activity) {164        activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE165    }166    private fun rotateToPortrait(activity: Activity) {167        activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT168    }169    private fun getCurrentActivity(): Activity? {...ViewModelTest.kt
Source:ViewModelTest.kt  
...51        Intents.intending(IntentMatchers.toPackage("com.pajato.argusremastered")).respondWith(result)52        onView(withId(R.id.fab))53                .perform(click())54        super.checkViewVisibility(withText(title), ViewMatchers.Visibility.VISIBLE)55        onView(allOf(withId(R.id.deleteButton), withParent(hasSibling(withText(title)))))56                .perform(click())57        onView(withText(title)).check(doesNotExist())58    }59    @Test fun testDelete() {60        val resultData = Intent()61        val title = "Thinger Strangs"62        resultData.putExtra(EnterActivity.TITLE_KEY, title)63        resultData.putExtra(EnterActivity.NETWORK_KEY, "Netflix")64        val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)65        Intents.intending(IntentMatchers.toPackage("com.pajato.argusremastered")).respondWith(result)66        onView(withId(R.id.fab))67                .perform(click())68        onView(allOf(withId(R.id.deleteButton), withParent(hasSibling(withText(title)))))69                .perform(click())70        onView(withText(title)).check(doesNotExist())71    }72    @Test fun testUpdate() {73        val resultData = Intent()74        val title = "Thinger Strangs"75        resultData.putExtra(EnterActivity.TITLE_KEY, title)76        resultData.putExtra(EnterActivity.NETWORK_KEY, "Netflix")77        val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)78        Intents.intending(IntentMatchers.toPackage("com.pajato.argusremastered")).respondWith(result)79        onView(withId(R.id.fab))80                .perform(click())81        onView(allOf(withId(R.id.dateButton), withParent(hasSibling(withText(title)))))82                .perform(click())83        checkViewVisibility(withText("A Date"), ViewMatchers.Visibility.VISIBLE)84        onView(allOf(withId(R.id.deleteButton), withParent(hasSibling(withText(title)))))85                .perform(click())86    }87    @Test88    fun testResult() {89        onView(withId(R.id.fab))90                .perform(click())91        checkViewVisibility(withId(R.id.searchActivityRoot), ViewMatchers.Visibility.VISIBLE)92        val text = "Luther"93        val network = "HBO Go"94        onView(withId(R.id.titleInput)).perform(replaceText(text))95        onView(withId(R.id.networkInput)).perform(replaceText(network))96        onView(withId(R.id.save)).perform(click())97    }98}...ViewMatchersTest.kt
Source:ViewMatchersTest.kt  
...19import android.support.test.espresso.matcher.RootMatchers.isTouchable20import android.support.test.espresso.matcher.ViewMatchers.hasContentDescription21import android.support.test.espresso.matcher.ViewMatchers.hasDescendant22import android.support.test.espresso.matcher.ViewMatchers.hasImeAction23import android.support.test.espresso.matcher.ViewMatchers.hasSibling24import android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom25import android.support.test.espresso.matcher.ViewMatchers.isChecked26import android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA27import android.support.test.espresso.matcher.ViewMatchers.isDisplayed28import android.support.test.espresso.matcher.ViewMatchers.isEnabled29import android.support.test.espresso.matcher.ViewMatchers.isFocusable30import android.support.test.espresso.matcher.ViewMatchers.isSelected31import android.support.test.espresso.matcher.ViewMatchers.supportsInputMethods32import android.support.test.espresso.matcher.ViewMatchers.withChild33import android.support.test.espresso.matcher.ViewMatchers.withClassName34import android.support.test.espresso.matcher.ViewMatchers.withContentDescription35import android.support.test.espresso.matcher.ViewMatchers.withHint36import android.support.test.espresso.matcher.ViewMatchers.withId37import android.support.test.espresso.matcher.ViewMatchers.withParent38import android.support.test.espresso.matcher.ViewMatchers.withText39import org.hamcrest.CoreMatchers.allOf40import org.hamcrest.CoreMatchers.`is`41import org.hamcrest.CoreMatchers.not42/**43 * Lists all ViewMatchers. ViewMatchers here are without functional load.44 * This is done for demonstration purposes.45 */46@RunWith(AndroidJUnit4::class)47class ViewMatchersTest {48    @Test49    fun userProperties() {50        onView(withId(R.id.fab_add_task))51        onView(withText("All TO-DOs"))52        onView(withContentDescription(R.string.menu_filter))53        onView(hasContentDescription())54        onView(withHint(R.string.name_hint))55    }56    @Test57    fun uiProperties() {58        onView(isDisplayed())59        onView(isEnabled())60        onView(isChecked())61        onView(isSelected())62    }63    @Test64    fun objectMatcher() {65        onView(not<View>(isChecked()))66        onView(allOf<View>(withText("item 1"), isChecked()))67    }68    @Test69    fun hierarchy() {70        onView(withParent(withId(R.id.todo_item)))71        onView(withChild(withText("item 2")))72        onView(isDescendantOfA(withId(R.id.todo_item)))73        onView(hasDescendant(isChecked()))74                .check(matches(isDisplayed()))75                .check(matches(isFocusable()))76        onView(hasSibling(withContentDescription(R.string.menu_filter)))77    }78    @Test79    fun input() {80        onView(supportsInputMethods())81        onView(hasImeAction(EditorInfo.IME_ACTION_SEND))82    }83    @Test84    fun classMatchers() {85        onView(isAssignableFrom(CheckBox::class.java))86        onView(withClassName(`is`(FloatingActionButton::class.java.canonicalName)))87    }88    @Test89    fun rootMatchers() {90        onView(isFocusable())...HistoryTester.kt
Source:HistoryTester.kt  
...5import android.support.test.espresso.assertion.ViewAssertions.doesNotExist6import android.support.test.espresso.assertion.ViewAssertions.matches7import android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition8import android.support.test.espresso.contrib.RecyclerViewActions.scrollToPosition9import android.support.test.espresso.matcher.ViewMatchers.hasSibling10import android.support.test.espresso.matcher.ViewMatchers.isDisplayed11import android.support.test.espresso.matcher.ViewMatchers.isSelected12import android.support.test.espresso.matcher.ViewMatchers.withId13import android.support.test.espresso.matcher.ViewMatchers.withText14import android.support.v7.widget.RecyclerView15import org.hamcrest.Matchers.allOf16import org.hamcrest.Matchers.not17import pl.srw.billcalculator.R18internal class HistoryTester internal constructor(parent: AppTester) : Tester() {19    private val billTester: BillTester = BillTester(parent)20    private var lastPosition: Int = 021    fun openBillWithReadings(from: String, to: String): BillTester {22        clickText("$from - $to")23        return billTester24    }25    fun openBillAtPosition(position: Int): BillTester {26        onView(withId(R.id.bill_list))27            .perform(actionOnItemAtPosition<RecyclerView.ViewHolder>(position, click()))28        return billTester29    }30    fun changeItemSelectionAtPosition(position: Int): HistoryTester {31        scrollToIndex(position)32        onView(withId(R.id.bill_list))33            .perform(actionOnItemAtPosition<RecyclerView.ViewHolder>(position, longClick()))34        return this35    }36    fun changeItemSelectionWithReadings(from: String, to: String): HistoryTester {37        onView(allOf(withId(R.id.history_item_logo), hasSibling(withText("$from - $to"))))38            .perform(click())39        return this40    }41    fun deleteBillWithReadings(from: String, to: String): HistoryTester {42        onView(withText("$from - $to"))43            .perform(swipeAwayRight())44        return this45    }46    fun deleteSelected(): HistoryTester {47        clickView(R.id.action_delete)48        return this49    }50    fun undoDelete(): HistoryTester {51        clickText(R.string.action_undo_delete)...TestList.kt
Source:TestList.kt  
...24    fun testShowListSucceful() {25        //verifica que se encuentre el texto '3y' dentro del listado que tiene como identificador el nombre del trabajo 'IBM'26        // ya que es un identificador unico dentro de las vistas de cada listado27        //allof = permite encontrar conjunciones de coincidencias multiples , no se llama a las coincidencias posteriorres si devuelve una anterior.28        //hasSibling = usado mayormente cuando un view que se quiere testear tiene un unico id dentro de un listado y contiene texto igual29        // con el hassibling hacemos que se limite la busqueda dandole algun identificaddor que este acompañado del texto que queremos testear este caso un30        //identificado para encontrar '3y' que es un texto que se repite31        onView(allOf(withText("3y"), hasSibling(withText("IBM")))).perform(click())32        //verificar si el texto es correcto dentro del adapter33//        onView(withId(R.id.rvJob)).check(matches(withText(containsString("KOTLIN Developer"))))34    }35    @Test36    fun scrolltoItemBelow_checkItsText() {37        //Scroleamos hasta la posicion que necesitamos hacerle match38        onView(ViewMatchers.withId(R.id.rvJob))39                .perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(ITEM_FOR_MATCH, click()))40        var itemElementText = testRule.activity.applicationContext.resources.getString(R.string.company_microfost)41        onView(withText(itemElementText)).check(matches(isDisplayed()))42    }43}...hasSibling
Using AI Code Generation
1ViewInteraction appCompatButton2 = onView(2allOf(withId(R.id.button2), withText("Button 2"),3hasSibling(withText("Button 1")),4isDisplayed()));5appCompatButton2.perform(click());6ViewInteraction appCompatButton3 = onView(7allOf(withId(R.id.button3), withText("Button 3"),8hasSibling(withText("Button 2")),9isDisplayed()));10appCompatButton3.perform(click());11ViewInteraction appCompatButton4 = onView(12allOf(withId(R.id.button4), withText("Button 4"),13hasSibling(withText("Button 3")),14isDisplayed()));15appCompatButton4.perform(click());16ViewInteraction appCompatButton5 = onView(17allOf(withId(R.id.button5), withText("Button 5"),18hasSibling(withText("Button 4")),19isDisplayed()));20appCompatButton5.perform(click());21ViewInteraction appCompatButton6 = onView(22allOf(withId(R.id.button6), withText("Button 6"),23hasSibling(withText("Button 5")),24isDisplayed()));25appCompatButton6.perform(click());26ViewInteraction appCompatButton7 = onView(27allOf(withId(R.id.button7), withText("Button 7"),28hasSibling(withText("Button 6")),29isDisplayed()));30appCompatButton7.perform(click());31ViewInteraction appCompatButton8 = onView(32allOf(withId(R.id.button8), withText("Button 8"),33hasSibling(withText("Button 7")),34isDisplayed()));35appCompatButton8.perform(click());36ViewInteraction appCompatButton9 = onView(37allOf(withId(R.id.button9), withText("Button 9"),38hasSibling(withText("Button 8")),39isDisplayed()));40appCompatButton9.perform(click());41ViewInteraction appCompatButton10 = onView(hasSibling
Using AI Code Generation
1ViewInteraction view = onView(withId(R.id.text1));2view.check(matches(hasSibling(withText("Text2"))));3ViewInteraction view = onView(withId(R.id.text1));4view.check(matches(hasSibling(withText("Text2"))));5ViewInteraction view = onView(withId(R.id.text1));6view.check(matches(hasSibling(withText("Text2"))));7ViewInteraction view = onView(withId(R.id.text1));8view.check(matches(hasSibling(withText("Text2"))));9ViewInteraction view = onView(withId(R.id.text1));10view.check(matches(hasSibling(withText("Text2"))));11ViewInteraction view = onView(withId(R.id.text1));12view.check(matches(hasSibling(withText("Text2"))));13ViewInteraction view = onView(withId(R.id.text1));14view.check(matches(hasSibling(withText("Text2"))));15ViewInteraction view = onView(withId(R.id.text1));16view.check(matches(hasSibling(withText("Text2"))));17ViewInteraction view = onView(withId(R.id.text1));18view.check(matches(hasSibling(withText("Text2"))));19ViewInteraction view = onView(withId(R.id.text1));20view.check(matches(hasSibling(withText("Text2"))));21ViewInteraction view = onView(withId(R.id.text1));22view.check(matches(hasSibling(withText("Text2"))));23ViewInteraction view = onView(withId(R.id.text1));24view.check(matches(hasSibling(withText("Text2"))));25ViewInteraction view = onView(withId(R.id.text1));26view.check(matches(hasSibling(withTexthasSibling
Using AI Code Generation
1ViewInteraction view = onView(2        allOf(withId(R.id.button),3                hasSibling(withText("Hello World!")),4                isDisplayed()));5view.perform(click());6ViewInteraction view = onView(7        allOf(withId(R.id.button),8                isDescendantOfA(withText("Hello World!")),9                isDisplayed()));10view.perform(click());11ViewInteraction view = onView(12        allOf(withId(R.id.button),13                withChild(withText("Hello World!")),14                isDisplayed()));15view.perform(click());16ViewInteraction view = onView(17        allOf(withId(R.id.button),18                withParent(withText("Hello World!")),19                isDisplayed()));20view.perform(click());21ViewInteraction view = onView(22        allOf(withId(R.id.button),23                withChild(withText("Hello World!")),24                isDisplayed()));25view.perform(click());26ViewInteraction view = onView(27        allOf(withId(R.id.button),28                withParent(withText("Hello World!")),29                isDisplayed()));30view.perform(click());31ViewInteraction view = onView(32        allOf(withId(R.id.button),33                withContentDescription("Hello World!"),34                isDisplayed()));35view.perform(click());36ViewInteraction view = onView(37        allOf(withId(R.id.button),38                withContentDescription("Hello World!"),39                isDisplayed()));40view.perform(click());41ViewInteraction view = onView(42        allOf(withId(R.id.button),43                withContentDescription("Hello World!"),44                isDisplayed()));45view.perform(click());46ViewInteraction view = onView(47        allOf(withId(R.id.button),48                withContentDescription("Hello World!"),49                isDisplayed()));50view.perform(click());hasSibling
Using AI Code Generation
1ViewInteraction view = onView(2                allOf(withId(R.id.button1), hasSibling(withId(R.id.button2)),3                        withParent(allOf(withId(R.id.layout1),4                                withParent(withId(android.R.id.content)))),5                        isDisplayed()));6        view.perform(click());7        ViewInteraction textView = onView(8                allOf(withId(R.id.textview), withText("Button 2 clicked"),9                        withParent(allOf(withId(R.id.layout1),10                                withParent(withId(android.R.id.content)))),11                        isDisplayed()));12        textView.check(matches(withText("Button 2 clicked")));13        ViewInteraction textView2 = onView(14                allOf(withId(R.id.textview), withText("Button 2 clicked"),15                        withParent(allOf(withId(R.id.layout1),16                                withParent(withId(android.R.id.content)))),17                        isDisplayed()));18        textView2.check(matches(withText("Button 2 clicked")));19        ViewInteraction button = onView(20                allOf(withId(R.id.button2), withText("Button 2"),21                        withParent(allOf(withId(R.id.layout1),22                                withParent(withId(android.R.id.content)))),23                        isDisplayed()));24        button.check(matches(isDisplayed()));25        ViewInteraction button2 = onView(26                allOf(withId(R.id.button2), withText("Button 2"),27                        withParent(allOf(withId(R.id.layout1),28                                withParent(withId(android.R.id.content)))),29                        isDisplayed()));30        button2.check(matches(isDisplayed()));31        ViewInteraction textView3 = onView(32                allOf(withId(R.id.textview), withText("Button 2 clicked"),33                        withParent(allOf(withId(R.id.layout1),34                                withParent(withId(android.R.id.content)))),35                        isDisplayed()));36        textView3.check(matches(withText("Button 2 clicked")));37        ViewInteraction button3 = onView(38                allOf(withId(R.id.button1), withText("Button 1"),39                        withParent(allOf(withId(R.id.layout1),40                                withParent(withId(android.R.id.content)))),41                        isDisplayed()));42        button3.check(matches(isDisplayed()));43        ViewInteraction button4 = onView(44                allOf(withId(R.id.button1), withText("Button 1"),45                        withParent(allOf(withId(R.id.layout1),46                                withParent(withId(android.R.id.content)))),47                        isDisplayed()));48        button4.check(matches(isDisplayed()));49        ViewInteraction textView4 = onView(50                allOf(withId(R.id.textview), withText("Button 1 clicked"),51                        withParent(allOf(withId(RhasSibling
Using AI Code Generation
1ViewInteraction appCompatImageView = onView(2allOf(withId(R.id.image_view),3hasSibling(allOf(withId(R.id.text_view),4withText("First"))),5isDisplayed()));6appCompatImageView.perform(click());7ViewInteraction appCompatImageView2 = onView(8allOf(withId(R.id.image_view),9hasSibling(allOf(withId(R.id.text_view),10withText("Second"))),11isDisplayed()));12appCompatImageView2.perform(click());13ViewInteraction appCompatImageView3 = onView(14allOf(withId(R.id.image_view),15hasSibling(allOf(withId(R.id.text_view),16withText("Third"))),17isDisplayed()));18appCompatImageView3.perform(click());19ViewInteraction appCompatImageView4 = onView(20allOf(withId(R.id.image_view),21hasSibling(allOf(withId(R.id.text_view),22withText("Fourth"))),23isDisplayed()));24appCompatImageView4.perform(click());25ViewInteraction appCompatImageView5 = onView(26allOf(withId(R.id.image_view),27hasSibling(allOf(withId(R.id.text_view),28withText("Fifth"))),29isDisplayed()));30appCompatImageView5.perform(click());31ViewInteraction appCompatImageView6 = onView(32allOf(withId(R.id.image_view),33hasSibling(allOf(withId(R.id.text_view),34withText("Sixth"))),35isDisplayed()));36appCompatImageView6.perform(click());37ViewInteraction appCompatImageView7 = onView(38allOf(withId(R.id.image_view),39hasSibling(allOf(withId(R.id.text_view),40withText("Seventh"))),41isDisplayed()));42appCompatImageView7.perform(click());hasSibling
Using AI Code Generation
1    onView(withId(R.id.my_view))2      .check(matches(hasSibling(withId(R.id.my_sibling_view))));3    onView(withId(R.id.my_view))4      .check(matches(hasSibling(withId(R.id.my_sibling_view))));5    onView(withId(R.id.my_view))6      .check(matches(hasSibling(withId(R.id.my_sibling_view))));7    onView(withId(R.id.my_view))8      .check(matches(hasSibling(withId(R.id.my_sibling_view))));9    onView(withId(R.id.my_view))10      .check(matches(hasSibling(withId(R.id.my_sibling_view))));11    onView(withId(R.id.my_view))12      .check(matches(hasSibling(withId(R.id.my_sibling_view))));13    onView(withId(R.id.my_view))14      .check(matches(hasSibling(withId(R.id.my_sibling_view))));15    onView(withId(R.id.my_view))16      .check(matches(hasSibling(withId(R.id.my_sibling_view))));17    onView(withId(R.id.my_view))18      .check(matches(hasSibling(withId(R.id.my_sibling_view))));19    onView(withId(R.id.my_view))20      .check(matches(hasSibling(withId(R.id.my_sibling_view))));Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
