/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 9 Ġ- Ġpresent ĠIn structure , ĠInc . Ċ Ġ* Ċ Ġ* ĠĠĠĠ ĠThis Ġprogram Ġis Ġfree Ġsoftware : Ġyou Ġcan Ġredistribute Ġit Ġand / or Ġmodify Ċ Ġ* ĠĠĠĠ Ġit Ġunder Ġthe Ġterms Ġof Ġthe ĠGNU ĠGeneral ĠPublic ĠLicense Ġas Ġpublished Ġby Ċ Ġ* ĠĠĠĠ Ġthe ĠFree ĠSoftware ĠFoundation , Ġversion Ġ 3 Ġof Ġthe ĠLicense . Ċ Ġ* Ċ Ġ* ĠĠĠĠ ĠThis Ġprogram Ġis Ġdistributed Ġin Ġthe Ġhope Ġthat Ġit Ġwill Ġbe Ġuseful , Ċ Ġ* ĠĠĠĠ Ġbut ĠWITHOUT ĠANY ĠWARRANTY ; Ġwithout Ġeven Ġthe Ġimplied Ġwarranty Ġof Ċ Ġ* ĠĠĠĠ ĠMERCHANTABILITY Ġor ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE . Ġ ĠSee Ġthe Ċ Ġ* ĠĠĠĠ ĠGNU ĠGeneral ĠPublic ĠLicense Ġfor Ġmore Ġdetails . Ċ Ġ* Ċ Ġ* ĠĠĠĠ ĠYou Ġshould Ġhave Ġreceived Ġa Ġcopy Ġof Ġthe ĠGNU ĠGeneral ĠPublic ĠLicense Ċ Ġ* ĠĠĠĠ Ġalong Ġwith Ġthis Ġprogram . Ġ ĠIf Ġnot , Ġsee Ġ< http :// www . gnu . org / licenses />. Ċ Ġ* Ċ Ġ*/ Ċ package Ġcom . in structure . canvas . espress o Ċ Ċ import Ġandroid . util . Display Metrics Ċ import Ġandroid . view . View Ċ import Ġandroid . widget . RadioButton Ċ import Ġandroid . widget . TextView Ċ import Ġandroidx . appcompat . widget . Toolbar Ċ import Ġandroidx . test . espress o . Esp ress o . on View Ċ import Ġandroidx . test . espress o . View Assertion Ċ import Ġandroidx . test . espress o . assertion . View Assertions . matches Ċ import Ġandroidx . test . espress o . matcher . Bounded Matcher Ċ import Ġandroidx . test . espress o . matcher . View Matchers . is Displayed Ċ import Ġandroidx . test . espress o . matcher . View Matchers . with Id Ċ import Ġandroidx . test . espress o . util . Human Read ables Ċ import Ġandroidx . test . espress o . util . Tree Iter ables Ċ import Ġcom . google . android . apps . common . testing . accessibility . framework . Accessibility View Check Result Ċ import Ġcom . google . android . material . text field . TextInput Layout Ċ import Ġcom . in structure . espress o . Activity Helper Ċ import Ġjunit . framework . Assertion Failed Error Ċ import Ġorg . hamcrest . Base Matcher Ċ import Ġorg . hamcrest . Description Ċ import Ġorg . hamcrest . Matcher Ċ import Ġorg . hamcrest . Type Safe Matcher Ċ Ċ // Ċ // ĠThis Ġis Ġa Ġrepo Ġfor Ġuseful Ġcustom Ġmatch ers Ċ // Ċ Ċ /** Ċ Ġ* ĠMat ches Ġif Ġthe Ġview Ġis Ġa ĠTextView Ġand Ġits Ġtext Ġcontains Ġ[ text To Match ], Ġcase Ġins ensitive Ċ Ġ*/ Ċ fun Ġcontains Text Case Ins ensitive ( text To Match : ĠString ) Ġ: ĠMatcher < View > Ġ{ ĊĠĠĠ Ġreturn Ġobject : ĠBase Matcher < View >() Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġmatches ( item : ĠAny ?): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen ( item ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠTextView Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġitem . text . toString (). contains ( text To Match , Ġignore Case Ġ= Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ?) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription ?. append Text (" check Ġto Ġsee Ġif ĠTextView Ġcontains Ġ\"$ text To Match \", Ġcase Ġins ensitive ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ // ĠSimilar Ġto Ġcontains Text Case Ins ensitive (), Ġbut Ġoper ates Ġon Ġa ĠString Ġrather Ġthan Ġa ĠTextView . Ċ // ĠOrigin ally Ġcreated Ġto Ġcom bat Ġsituations Ġwhere Ġa Ġcontent Ġdescription Ġcontains Ġgarbage Ġcharacters . Ċ fun Ġstring Contains Text Case Ins ensitive ( text To Match : ĠString ) Ġ: ĠMatcher < String > Ġ{ ĊĠĠĠ Ġreturn Ġobject : ĠBase Matcher < String >() Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġmatches ( item : ĠAny ?): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen ( item ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠString Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġitem . contains ( text To Match , Ġignore Case Ġ= Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ?) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription ?. append Text (" check Ġto Ġsee Ġif ĠString Ġcontains Ġ\"$ text To Match \", Ġcase Ġins ensitive ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠReturns Ġtrue Ġif Ġthe Ġelement Ġwith Ġthe Ġgiven Ġresource Ġid Ġis Ġcurrently Ġdisplayed , Ġfalse Ġotherwise . Ċ Ġ*/ Ċ fun Ġis Element Displayed ( resourceId : ĠInt ) Ġ: ĠBoolean Ġ{ ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġon View ( with Id ( resourceId )). check ( matches ( is Displayed ())) ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĠĠĠ Ġcatch ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} Ċ } Ċ Ċ inline Ġfun Ġ< re ified ĠT Ġ: ĠView > Ġtyped View Condition ( cross inline Ġon Check Condition : Ġ( T ) Ġ-> ĠBoolean ): ĠMatcher < View > Ġ{ ĊĠĠĠ Ġreturn Ġobject Ġ: ĠBase Matcher < View >() Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġmatches ( item : ĠAny ?): ĠBoolean Ġ= Ġ( item Ġas ? ĠT )?. let ( on Check Condition ) Ġ?: Ġfalse ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ?) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription ?. append Text (" matches Ġview Ġtype Ġ'${ T :: class . java . simple Name }' Ġand Ġfulfill s Ġthe Ġgiven Ġcondition ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġchecked ( checked : ĠBoolean Ġ= Ġtrue , Ġindex : ĠInt Ġ= Ġ 0 , ĠgetText : Ġ( String ) Ġ-> ĠUnit Ġ= Ġ{} ): ĠBo unded Matcher < View , ĠRadio Button > Ġ{ ĊĠĠĠ Ġreturn Ġobject Ġ: ĠBo unded Matcher < View , ĠRadio Button >( RadioButton :: class . java ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar ĠcurrentIndex Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription . append Text (" selected Ġradio Ġbutton Ġ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġmatches S af ely ( item : ĠRadio Button ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( index Ġ== ĠcurrentIndex ++ Ġ&& Ġitem . isChecked Ġ== Ġchecked ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetText ( item . text . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠcurrentIndex -- ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* Ġ@ param Ġmatch Title ĠTrue Ġif Ġmatching Ġwith Ġtitle , Ġfalse Ġif Ġmatching Ġwith Ġsubtitle Ċ Ġ*/ Ċ fun Ġmatch Toolbar Text ( match Text : ĠMatcher < String >, Ġmatch Title : ĠBoolean Ġ= Ġtrue ): ĠBo unded Matcher < View , ĠToolbar > Ġ{ ĊĠĠĠ Ġreturn Ġobject Ġ: ĠBo unded Matcher < View , ĠToolbar >( Toolbar :: class . java ) Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription . append Text (" with Ġtoolbar Ġ${ if Ġ( match Title ) Ġ" title " Ġelse Ġ" subtitle "} Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmatch Text . describe To ( description ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġmatches S af ely ( view : ĠToolbar ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġmatch Text . matches ( if Ġ( match Title ) Ġview . title Ġelse Ġview . subtitle ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġhas ( expected Count : ĠInt , Ġselector : ĠMatcher < View >): ĠView Assertion Ġ{ ĊĠĠĠ Ġreturn ĠView Assertion Ġ{ Ġview , Ġno View Found Exception Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġroot View Ġ= Ġview ĊĊĠĠĠĠĠĠĠ Ġval Ġdesc endant Views Ġ= ĠTree Iter ables . bread th First View Traversal ( root View ) ĊĠĠĠĠĠĠĠ Ġval Ġselected Views Ġ= ĠArrayList < View >() ĊĠĠĠĠĠĠĠ Ġdesc endant Views . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( selector . matches ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselected Views . add ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( selected Views . size Ġ!= Ġexpected Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠerrorMessage Ġ= ĠHuman Read ables . getView Hierarchy ErrorMessage ( root View , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselected Views , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠString . format (" Found Ġ% d Ġviews Ġinstead Ġof Ġ% d Ġmatching : Ġ% s ", Ġselected Views . size , Ġexpected Count , Ġselector ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" **** MATCH ES **** ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠAssertion Failed Error ( errorMessage ); ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġhas TextInput Layout Error Text ( string Res Id : ĠInt ): ĠMatcher < View > Ġ{ ĊĠĠĠ Ġreturn Ġobject Ġ: ĠType Safe Matcher < View >() Ġ{ ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġmatches S af ely ( view : ĠView ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( view Ġ! is ĠText Input Layout ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġerror Ġ= Ġview . error Ġ?: Ġreturn Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhint Ġ= Ġerror . toString () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġactual ErrorMsg Ġ= Ġview . resources . getString ( string Res Id ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġactual ErrorMsg Ġ== Ġhint ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ) Ġ{} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġwith Index ( matcher : ĠMatcher < View >, Ġindex : ĠInt ): ĠMatcher < View > Ġ{ ĊĠĠĠ Ġreturn Ġobject Ġ: ĠType Safe Matcher < View >() Ġ{ ĊĠĠĠĠĠĠĠ Ġinternal Ġvar ĠcurrentIndex Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription . append Text (" with Ġindex : Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription . append Value ( index ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmatcher . describe To ( description ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġpublic Ġoverride Ġfun Ġmatches S af ely ( view : ĠView ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġmatcher . matches ( view ) Ġ&& ĠcurrentIndex ++ Ġ== Ġindex ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ // ĠA Ġmatcher Ġfor Ġviews Ġwhose Ġwidth Ġis Ġless Ġthan Ġthe Ġspecified Ġamount Ġ( in Ġdp ), Ċ // Ġbut Ġwhose Ġheight Ġis Ġat Ġleast Ġthe Ġspecified Ġamount . Ċ // ĠThis Ġis Ġused Ġto Ġsuppress Ġaccessibility Ġfailures Ġrelated Ġto Ġoverflow Ġmenus Ċ // Ġin Ġaction Ġbars Ġbeing Ġto Ġnarrow . Ċ fun Ġwith Only Width LessThan ( dim In Dp : ĠInt ) Ġ: ĠBase Matcher < Accessibility View Check Result > Ċ { ĊĠĠĠ Ġval Ġdensity D pi Ġ= ĠActivity Helper . current Activity (). resources . display Metrics . density D pi ĊĠĠĠ Ġval Ġdim _ f Ġ= Ġdim In Dp Ġ* Ġ( density D pi . toDouble () Ġ/ ĠDisplay Metrics . D ENS ITY _ DEFAULT . toDouble ()) ĊĠĠĠ Ġval Ġdim Ġ= Ġdim _ f . toInt () ĊĠĠĠ Ġreturn Ġobject Ġ: ĠBase Matcher < Accessibility View Check Result >() Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdescribe To ( description : ĠDescription ?) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdescription ?. append Text (" checking Ġwhether Ġwidth Ġ< Ġ$ dim Ġ&& Ġheight Ġ>= Ġ$ dim ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġmatches ( item : ĠAny ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen ( item ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠAccessibility View Check Result Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġitem . view . width Ġ< Ġdim Ġ&& Ġitem . view . height Ġ>= Ġdim ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} Ċ }