How to use withContentDescription method of android.support.test.espresso.matcher.ViewMatchers class

Best Appium-espresso-driver code snippet using android.support.test.espresso.matcher.ViewMatchers.withContentDescription

MainActivityTest2.kt

Source:MainActivityTest2.kt Github

copy

Full Screen

...74 3),75 ViewMatchers.isDisplayed()))76 snackbarLayout.perform(ViewActions.click())77 val appCompatImageButton = Espresso.onView(78 Matchers.allOf(ViewMatchers.withContentDescription("Open navigation drawer"),79 childAtPosition(80 Matchers.allOf(ViewMatchers.withId(R.id.toolbar),81 childAtPosition(82 ViewMatchers.withClassName(Matchers.`is`("android.support.design.widget.AppBarLayout")),83 0)),84 1),85 ViewMatchers.isDisplayed()))86 appCompatImageButton.perform(ViewActions.click())87 val navigationMenuItemView = Espresso.onView(88 Matchers.allOf(childAtPosition(89 Matchers.allOf(ViewMatchers.withId(R.id.design_navigation_view),90 childAtPosition(91 ViewMatchers.withId(R.id.nav_view),92 0)),93 1),94 ViewMatchers.isDisplayed()))95 navigationMenuItemView.perform(ViewActions.click())96 val appCompatImageButton2 = Espresso.onView(97 Matchers.allOf(ViewMatchers.withContentDescription("Open navigation drawer"),98 childAtPosition(99 Matchers.allOf(ViewMatchers.withId(R.id.toolbar),100 childAtPosition(101 ViewMatchers.withClassName(Matchers.`is`("android.support.design.widget.AppBarLayout")),102 0)),103 1),104 ViewMatchers.isDisplayed()))105 appCompatImageButton2.perform(ViewActions.click())106 val navigationMenuItemView2 = Espresso.onView(107 Matchers.allOf(childAtPosition(108 Matchers.allOf(ViewMatchers.withId(R.id.design_navigation_view),109 childAtPosition(110 ViewMatchers.withId(R.id.nav_view),111 0)),112 3),113 ViewMatchers.isDisplayed()))114 navigationMenuItemView2.perform(ViewActions.click())115 val appCompatImageButton3 = Espresso.onView(116 Matchers.allOf(ViewMatchers.withContentDescription("Open navigation drawer"),117 childAtPosition(118 Matchers.allOf(ViewMatchers.withId(R.id.toolbar),119 childAtPosition(120 ViewMatchers.withClassName(Matchers.`is`("android.support.design.widget.AppBarLayout")),121 0)),122 1),123 ViewMatchers.isDisplayed()))124 appCompatImageButton3.perform(ViewActions.click())125 val navigationMenuItemView3 = Espresso.onView(126 Matchers.allOf(childAtPosition(127 Matchers.allOf(ViewMatchers.withId(R.id.design_navigation_view),128 childAtPosition(129 ViewMatchers.withId(R.id.nav_view),130 0)),131 2),132 ViewMatchers.isDisplayed()))133 navigationMenuItemView3.perform(ViewActions.click())134 val appCompatImageButton1 = Espresso.onView(135 Matchers.allOf(ViewMatchers.withContentDescription("Open navigation drawer"),136 childAtPosition(137 Matchers.allOf(ViewMatchers.withId(R.id.toolbar),138 childAtPosition(139 ViewMatchers.withClassName(Matchers.`is`("android.support.design.widget.AppBarLayout")),140 0)),141 1),142 ViewMatchers.isDisplayed()))143 appCompatImageButton1.perform(ViewActions.click())144 Espresso.pressBack()145 }146 companion object {147 private fun childAtPosition(148 parentMatcher: Matcher<View>, position: Int): Matcher<View> {149 return object : TypeSafeMatcher<View>() {...

Full Screen

Full Screen

MainActivityTest.kt

Source:MainActivityTest.kt Github

copy

Full Screen

...18import android.support.test.espresso.assertion.ViewAssertions.matches19import android.support.test.espresso.contrib.RecyclerViewActions20import android.support.test.espresso.matcher.ViewMatchers.isDisplayed21import android.support.test.espresso.matcher.ViewMatchers.withClassName22import android.support.test.espresso.matcher.ViewMatchers.withContentDescription23import android.support.test.espresso.matcher.ViewMatchers.withId24import android.support.test.espresso.matcher.ViewMatchers.withText25import android.support.v7.widget.RecyclerView26import org.hamcrest.Matchers.allOf27import org.hamcrest.Matchers.`is`28@LargeTest29@RunWith(AndroidJUnit4::class)30class MainActivityTest {31 @Rule32 @JvmField33 var mActivityTestRule = ActivityTestRule(MainActivity::class.java)34 @Test35 fun mainActivityTest() {36 val bottomNavigationItemView = onView(37 allOf(withId(R.id.menu_next_event),38 childAtPosition(39 childAtPosition(40 withId(R.id.navigation),41 0),42 1),43 isDisplayed()))44 bottomNavigationItemView.perform(click())45 Thread.sleep(3000)46 val cardView = onView(47 allOf(childAtPosition(48 childAtPosition(49 withClassName(`is`("org.jetbrains.anko._RelativeLayout")),50 0),51 1),52 isDisplayed()))53 cardView.perform(click())54 Thread.sleep(3000)55 val textView = onView(56 allOf(withId(R.id.home_team_name), withText("West Ham"),57 childAtPosition(58 childAtPosition(59 IsInstanceOf.instanceOf(android.widget.LinearLayout::class.java),60 0),61 1),62 isDisplayed()))63 textView.check(matches(withText("West Ham")))64 val imageView = onView(65 allOf(withId(R.id.img_away_badge_team),66 childAtPosition(67 childAtPosition(68 IsInstanceOf.instanceOf(android.widget.LinearLayout::class.java),69 2),70 0),71 isDisplayed()))72 imageView.check(matches(isDisplayed()))73 val actionMenuItemView = onView(74 allOf(withId(R.id.add_to_favorite), withContentDescription("Favorites"),75 childAtPosition(76 childAtPosition(77 withId(R.id.action_bar),78 1),79 0),80 isDisplayed()))81 actionMenuItemView.perform(click())82 pressBack()83 val bottomNavigationItemView2 = onView(84 allOf(withId(R.id.menu_favorite_event),85 childAtPosition(86 childAtPosition(87 withId(R.id.navigation),88 0),89 2),90 isDisplayed()))91 bottomNavigationItemView2.perform(click())92 Thread.sleep(3000)93 onView(withId(R.id.list_favorite)).perform(94 RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(0, click()))95 val actionMenuItemView2 = onView(96 allOf(withId(R.id.add_to_favorite), withContentDescription("Favorites"),97 childAtPosition(98 childAtPosition(99 withId(R.id.action_bar),100 1),101 0),102 isDisplayed()))103 actionMenuItemView2.perform(click())104 }105 private fun childAtPosition(106 parentMatcher: Matcher<View>, position: Int): Matcher<View> {107 return object : TypeSafeMatcher<View>() {108 override fun describeTo(description: Description) {109 description.appendText("Child at position $position in parent ")110 parentMatcher.describeTo(description)...

Full Screen

Full Screen

MainActivityUITest.kt

Source:MainActivityUITest.kt Github

copy

Full Screen

...49 @Test50 fun categorieNavClicked() {51 val bottomNavigationItemView = onView(52 Matchers.allOf(53 withId(R.id.categories), ViewMatchers.withContentDescription("Categories"),54 childAtPosition(55 childAtPosition(56 withId(R.id.bottom_navigation),57 058 ),59 160 ),61 ViewMatchers.isDisplayed()62 )63 )64 bottomNavigationItemView.perform(click())65 val fragment= ListenerUtil.getSelectedFragment()66 Assert.assertEquals(CategoriesFragment()::class.java, fragment::class.java)67 }68 @Test69 fun favouritesNavClicked() {70 val bottomNavigationItemView = onView(71 Matchers.allOf(72 withId(R.id.favourites), ViewMatchers.withContentDescription("Favourites"),73 childAtPosition(74 childAtPosition(75 withId(R.id.bottom_navigation),76 077 ),78 279 ),80 ViewMatchers.isDisplayed()81 )82 )83 bottomNavigationItemView.perform(click())84 val fragment= ListenerUtil.getSelectedFragment()85 Assert.assertEquals(FavouritesFragment()::class.java, fragment::class.java)86 }87 @Test88 fun settingsNavClicked() {89 val bottomNavigationItemView = onView(90 Matchers.allOf(91 withId(R.id.settings), ViewMatchers.withContentDescription("Settings"),92 childAtPosition(93 childAtPosition(94 withId(R.id.bottom_navigation),95 096 ),97 398 ),99 ViewMatchers.isDisplayed()100 )101 )102 bottomNavigationItemView.perform(click())103 val fragment= ListenerUtil.getSelectedFragment()104 Assert.assertEquals(SettingsFragment()::class.java, fragment::class.java)105 }106 @Test107 fun wallpapersNavClicked() {108 val bottomNavigationItemView = onView(109 Matchers.allOf(110 withId(R.id.wallpapers), ViewMatchers.withContentDescription("Wallpapers"),111 childAtPosition(112 childAtPosition(113 withId(R.id.bottom_navigation),114 0115 ),116 0117 ),118 ViewMatchers.isDisplayed()119 )120 )121 bottomNavigationItemView.perform(click())122 val fragment= ListenerUtil.getSelectedFragment()123 Assert.assertEquals(WallpaperFragment()::class.java, fragment::class.java)124 }...

Full Screen

Full Screen

ViewMatchersTest.kt

Source:ViewMatchersTest.kt Github

copy

Full Screen

...30import 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())...

Full Screen

Full Screen

DrawingTest.kt

Source:DrawingTest.kt Github

copy

Full Screen

...14import android.support.test.espresso.Espresso.pressBack15import android.support.test.espresso.action.ViewActions.click16import android.support.test.espresso.action.ViewActions.scrollTo17import android.support.test.espresso.matcher.ViewMatchers.isDisplayed18import android.support.test.espresso.matcher.ViewMatchers.withContentDescription19import android.support.test.espresso.matcher.ViewMatchers.withId20import android.support.test.espresso.matcher.ViewMatchers.withText21import org.hamcrest.Matchers.allOf22@android.test.suitebuilder.annotation.SmallTest23@RunWith(AndroidJUnit4::class)24class DrawingTest {25 @Rule26 var mActivityTestRule = ActivityTestRule(LoginActivity::class.java)27 @Test28 fun drawingTest() {29 // Added a sleep statement to match the app's execution delay.30 // The recommended way to handle such scenarios is to use Espresso idling resources:31 // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html32 try {33 Thread.sleep(60000)34 } catch (e: InterruptedException) {35 e.printStackTrace()36 }37 pressBack()38 val appCompatButton = onView(39 allOf(withId(R.id.btn_skip_to_draw), withText("Skip To Draw")))40 appCompatButton.perform(scrollTo(), click())41 // Added a sleep statement to match the app's execution delay.42 // The recommended way to handle such scenarios is to use Espresso idling resources:43 // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html44 try {45 Thread.sleep(3590788)46 } catch (e: InterruptedException) {47 e.printStackTrace()48 }49 val actionMenuItemView = onView(50 allOf(withId(R.id.menu_start_scan), withContentDescription("Start Scan"), isDisplayed()))51 actionMenuItemView.perform(click())52 // Added a sleep statement to match the app's execution delay.53 // The recommended way to handle such scenarios is to use Espresso idling resources:54 // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html55 try {56 Thread.sleep(10000)57 } catch (e: InterruptedException) {58 e.printStackTrace()59 }60 val relativeLayout = onView(61 allOf(childAtPosition(62 withId(R.id.nodeListView),63 0),64 isDisplayed()))65 relativeLayout.perform(click())66 // Added a sleep statement to match the app's execution delay.67 // The recommended way to handle such scenarios is to use Espresso idling resources:68 // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html69 try {70 Thread.sleep(3589733)71 } catch (e: InterruptedException) {72 e.printStackTrace()73 }74// val actionMenuItemView2 = onView(75// allOf(withId(R.id.menu_startResumeMovement), withContentDescription("Start Movement Tracking"), isDisplayed()))76// actionMenuItemView2.perform(click())77//78// val actionMenuItemView3 = onView(79// allOf(withId(R.id.menu_stopMovement), withContentDescription("Pause Movement Tracking"), isDisplayed()))80// actionMenuItemView3.perform(click())81 }82 private fun childAtPosition(83 parentMatcher: Matcher<View>, position: Int): Matcher<View> {84 return object : TypeSafeMatcher<View>() {85 override fun describeTo(description: Description) {86 description.appendText("Child at position $position in parent ")87 parentMatcher.describeTo(description)88 }89 public override fun matchesSafely(view: View): Boolean {90 val parent = view.parent91 return parent is ViewGroup && parentMatcher.matches(parent)92 && view == parent.getChildAt(position)93 }...

Full Screen

Full Screen

ProductActivityTest.kt

Source:ProductActivityTest.kt Github

copy

Full Screen

...5import androidx.test.espresso.action.ViewActions.click6import androidx.test.espresso.assertion.ViewAssertions.matches7import androidx.test.espresso.matcher.ViewMatchers.isDisplayed8import androidx.test.espresso.matcher.ViewMatchers.withText9import androidx.test.espresso.matcher.ViewMatchers.withContentDescription10import androidx.test.espresso.matcher.ViewMatchers.withId11import androidx.test.ext.junit.runners.AndroidJUnit412import androidx.test.filters.LargeTest13import androidx.test.rule.ActivityTestRule14import com.designdemo.uaha.view.product.ProductActivity15import com.support.android.designlibdemo.BuildConfig16import com.support.android.designlibdemo.R17import org.hamcrest.Description18import org.hamcrest.Matcher19import org.hamcrest.Matchers.allOf20import org.hamcrest.TypeSafeMatcher21import org.junit.Before22import org.junit.Rule23import org.junit.Test24import org.junit.runner.RunWith25@LargeTest26@RunWith(AndroidJUnit4::class)27class ProductActivityTest {28 lateinit var versionName: String29 var versionCode = 030 @Rule31 @JvmField32 var mActivityTestRule = ActivityTestRule(ProductActivity::class.java)33 @Before34 fun initStringsEntered() {35 versionName = BuildConfig.VERSION_NAME36 versionCode = BuildConfig.VERSION_CODE37 }38 @Test39 fun versionNameVerificationTest() {40 val appCompatImageButton = onView(allOf(withContentDescription("Navigate up"), childAtPosition(allOf(withId(R.id.bottom_appbar), childAtPosition(withId(R.id.user_main_coordinator), 1)), 1), isDisplayed()))41 appCompatImageButton.perform(click())42 val textView = onView(allOf(withId(R.id.header_versioninfo), withText("Version: $versionName ($versionCode)"), childAtPosition(childAtPosition(withId(R.id.navigation_header_container), 0), 1), isDisplayed()))43 textView.check(matches(withText("Version: $versionName ($versionCode)")))44 }45 @Test46 fun checkMenuCorrectTest() {47 val appCompatImageButton = onView(allOf(withContentDescription("Navigate up"), childAtPosition(allOf(withId(R.id.bottom_appbar), childAtPosition(withId(R.id.user_main_coordinator), 1)), 1), isDisplayed()))48 appCompatImageButton.perform(click())49 val checkedTextView = onView(allOf(withId(R.id.design_menu_item_text), childAtPosition(childAtPosition(withId(R.id.design_navigation_view), 1), 0), isDisplayed()))50 checkedTextView.check(matches(isDisplayed()))51 }52 private fun childAtPosition(parentMatcher: Matcher<View>, position: Int): Matcher<View> {53 return object : TypeSafeMatcher<View>() {54 override fun describeTo(description: Description) {55 description.appendText("Child at position $position in parent ")56 parentMatcher.describeTo(description)57 }58 public override fun matchesSafely(view: View): Boolean {59 val parent = view.parent60 return parent is ViewGroup && parentMatcher.matches(parent) && view == parent.getChildAt(position)61 }...

Full Screen

Full Screen

TestMainActivityMenuDrawerButtonOpeningNotificationActivity.kt

Source:TestMainActivityMenuDrawerButtonOpeningNotificationActivity.kt Github

copy

Full Screen

...3import android.support.test.espresso.action.ViewActions4import android.support.test.espresso.assertion.ViewAssertions5import android.support.test.espresso.assertion.ViewAssertions.matches6import android.support.test.espresso.matcher.ViewMatchers7import android.support.test.espresso.matcher.ViewMatchers.withContentDescription8import android.support.test.runner.AndroidJUnit49import org.junit.Before10import org.junit.runner.RunWith11import org.junit.Rule12import org.junit.Test13import org.junit.rules.TestRule14import android.support.test.rule.ActivityTestRule15import org.hamcrest.CoreMatchers.containsString16import android.support.test.espresso.intent.Intents.intended17import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;18import android.support.test.espresso.intent.rule.IntentsTestRule19@RunWith(AndroidJUnit4::class)20class TestMainActivityMenuDrawerButtonOpeningNotificationActivity {21 @get:Rule22 var mActivityRule: IntentsTestRule<MainActivity> = IntentsTestRule(MainActivity::class.java)23 @Before24 fun setUp() {25 }26// @Test27// fun isThatOpeningSearchActivity(){28//29//30// // GIVEN - On the home screen31// Espresso.onView(ViewMatchers.withId(R.id.action_search))32//33// // WHEN - Click on the "+" button34// .perform(ViewActions.click())35//36// // THEN - Verify that we navigate to the add screen37// // .check(matches(withContentDescription(containsString("Search"))))38// // check is activity was started39// intended(hasComponent(SearchActivity::class.java.getName()))40// }41 @Test42 fun isThatOpeningNotificationActivity() {43 // GIVEN - On the home screen44 Espresso.onView(ViewMatchers.withId(R.id.action_notification))45 // WHEN - Click on the "+" button46 .perform(ViewActions.click())47 // THEN - Verify that we navigate to the add screen48 // .check(matches(withContentDescription(containsString("Search"))))49 // check is activity was started50 intended(hasComponent(NotificationActivity::class.java.getName()))51 }52}...

Full Screen

Full Screen

TestMainActivityIconButtonOpeningSearchActivity.kt

Source:TestMainActivityIconButtonOpeningSearchActivity.kt Github

copy

Full Screen

...3import android.support.test.espresso.action.ViewActions4import android.support.test.espresso.assertion.ViewAssertions5import android.support.test.espresso.assertion.ViewAssertions.matches6import android.support.test.espresso.matcher.ViewMatchers7import android.support.test.espresso.matcher.ViewMatchers.withContentDescription8import android.support.test.runner.AndroidJUnit49import org.junit.Before10import org.junit.runner.RunWith11import org.junit.Rule12import org.junit.Test13import org.junit.rules.TestRule14import android.support.test.rule.ActivityTestRule15import org.hamcrest.CoreMatchers.containsString16import android.support.test.espresso.intent.Intents.intended17import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;18import android.support.test.espresso.intent.rule.IntentsTestRule19@RunWith(AndroidJUnit4::class)20class TestMainActivityIconButtonOpeningSearchActivity {21 @get:Rule22 var mActivityRule: IntentsTestRule<MainActivity> = IntentsTestRule(MainActivity::class.java)23 @Before24 fun setUp() {25 }26 @Test27 fun isThatOpeningSearchActivity(){28 // GIVEN - On the home screen29 Espresso.onView(ViewMatchers.withId(R.id.action_search))30 // WHEN - Click on the "+" button31 .perform(ViewActions.click())32 // THEN - Verify that we navigate to the add screen33 // .check(matches(withContentDescription(containsString("Search"))))34 // check is activity was started35 intended(hasComponent(SearchActivity::class.java.getName()))36 }37// @Test38// fun isThatOpeningNotificationActivity(){39//40//41// // GIVEN - On the home screen42// Espresso.onView(ViewMatchers.withId(R.id.action_notification))43//44// // WHEN - Click on the "+" button45// .perform(ViewActions.click())46//47// // THEN - Verify that we navigate to the add screen48// // .check(matches(withContentDescription(containsString("Search"))))49// // check is activity was started50// intended(hasComponent(NotificationActivity::class.java.getName()))51// }52}...

Full Screen

Full Screen

withContentDescription

Using AI Code Generation

copy

Full Screen

1ViewInteraction view = onView(2allOf(withId(R.id.button), withContentDescription("button")));3ViewInteraction view = onView(4allOf(withId(R.id.button), withText("button")));5ViewInteraction view = onView(6allOf(withId(R.id.button), withText(R.string.button)));7ViewInteraction view = onView(8allOf(withId(R.id.button), withText("button")));9ViewInteraction view = onView(10allOf(withId(R.id.button), withText("button")));11ViewInteraction view = onView(12allOf(withId(R.id.button), withText("button")));13ViewInteraction view = onView(14allOf(withId(R.id.button), withText("button")));15ViewInteraction view = onView(16allOf(withId(R.id.button), withText("button")));17ViewInteraction view = onView(18allOf(withId(R.id.button), withText("button")));19ViewInteraction view = onView(20allOf(withId(R.id.button), withText("button")));21ViewInteraction view = onView(22allOf(withId(R.id.button), withText("button")));23ViewInteraction view = onView(24allOf(withId(R.id.button), withText("button")));25ViewInteraction view = onView(26allOf(withId(R.id.button), withText("button")));27ViewInteraction view = onView(28allOf(withId(R.id.button), withText("button")));29ViewInteraction view = onView(

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful