/* Ċ Ġ* ĠCopyright Ġ 2 0 2 0 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġandroidx . compose . runtime Ċ Ċ import Ġandroid . view . View Ċ import Ġandroid . view . ViewGroup Ċ import Ġandroid . widget . LinearLayout Ċ import Ġandroid . widget . TextView Ċ import Ġandroidx . compose . runtime . snapshots . current Snapshot Ċ import Ġandroidx . test . ext . junit . runners . Android JUnit 4 Ċ import Ġandroidx . test . filters . Medium Test Ċ import Ġjunit . framework . TestCase . assertEquals Ċ import Ġjunit . framework . TestCase . assertFalse Ċ import Ġjunit . framework . TestCase . assertNot Same Ċ import Ġjunit . framework . TestCase . assertTrue Ċ import Ġorg . junit . After Ċ import Ġorg . junit . Rule Ċ import Ġorg . junit . Test Ċ import Ġorg . junit . runner . RunWith Ċ import Ġkotlin . test . assertNotNull Ċ Ċ @ Medium Test Ċ @ RunWith ( Android JUnit 4 :: class ) Ċ class ĠRe composer Tests Ġ: ĠBase Compose Test () Ġ{ ĊĠĠĠ Ġ@ After ĊĠĠĠ Ġfun Ġteardown () Ġ{ ĊĠĠĠĠĠĠĠ Ġclear Roots () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ get : Rule ĊĠĠĠ Ġoverride Ġval Ġactivity Rule Ġ= Ġmake Test Activity Rule () ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Native View With Attributes () Ġ{ ĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTextView ( id Ġ= Ġ 4 5 6 , Ġtext Ġ= Ġ" some Ġtext ") ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġactivity . root . child Count ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtv Ġ= Ġactivity . findViewById ( 4 5 6 ) Ġas ĠTextView ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" some Ġtext ", Ġtv . text ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( tv , Ġactivity . root . getChild At ( 0 )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Slot Key Change Cause s Re create () Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġi Ġ= Ġ 1 ĊĠĠĠĠĠĠĠ Ġvar Ġtv 1 : ĠTextView ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġtrigger Ġ= ĠTrigger () ĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtrigger . subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthis Ġshould Ġcause Ġthe Ġtext view Ġto Ġget Ġre created Ġon Ġevery Ġcompose ĊĠĠĠĠĠĠĠĠĠĠĠ Ġi ++ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġkey ( i ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTextView ( id Ġ= Ġ 4 5 6 , Ġtext Ġ= Ġ" some Ġtext ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtv 1 Ġ= Ġactivity . findViewById ( 4 5 6 ) Ġas ĠTextView ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtrigger . re compose () ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" Compose Ġgot Ġcalled Ġtwice ", Ġ 3 , Ġi ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtv 2 Ġ= Ġactivity . findViewById ( 4 5 6 ) Ġas ĠTextView ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" The Ġtext Ġviews Ġshould Ġbe Ġdifferent Ġinstances ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtv 1 Ġ=== Ġtv 2 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" The Ġunused Ġchild Ġgot Ġremoved Ġfrom Ġthe Ġview Ġhierarchy ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġactivity . root . child Count ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest View With View Children () Ġ{ ĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout ( id Ġ= Ġ 3 4 5 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTextView ( id Ġ= Ġ 4 5 6 , Ġtext Ġ= Ġ" some Ġtext ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTextView ( id Ġ= Ġ 5 6 7 , Ġtext Ġ= Ġ" some Ġtext ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġll Ġ= Ġactivity . findViewById ( 3 4 5 ) Ġas ĠLinearLayout ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtv 1 Ġ= Ġactivity . findViewById ( 4 5 6 ) Ġas ĠTextView ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtv 2 Ġ= Ġactivity . findViewById ( 5 6 7 ) Ġas ĠTextView ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" The Ġlinear Ġlayout Ġshould Ġbe Ġthe Ġonly Ġchild Ġof Ġroot ", Ġ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġactivity . root . child Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" Both Ġchildren Ġshould Ġhave Ġbeen Ġadded ", Ġ 2 , Ġll . child Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Should Ġbe Ġthe Ġexpected ĠTextView Ġ( 1 )", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġll . getChild At ( 0 ) Ġ=== Ġtv 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Should Ġbe Ġthe Ġexpected ĠTextView Ġ( 2 )", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġll . getChild At ( 1 ) Ġ=== Ġtv 2 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest For Loop () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġitems Ġ= ĠlistOf ( 1 , Ġ 2 , Ġ 3 , Ġ 4 , Ġ 5 , Ġ 6 ) ĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout ( id Ġ= Ġ 3 4 5 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġitems ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTextView ( id Ġ= Ġ 4 5 6 , Ġtext Ġ= Ġ" some Ġtext Ġ$ i ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġll Ġ= Ġactivity . findViewById ( 3 4 5 ) Ġas ĠLinearLayout ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" The Ġlinear Ġlayout Ġshould Ġbe Ġthe Ġonly Ġchild Ġof Ġroot ", Ġ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġactivity . root . child Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" Each Ġitem Ġin Ġthe Ġfor Ġloop Ġshould Ġbe Ġa Ġchild ", Ġitems . size , Ġll . child Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġitems . forEach Indexed Ġ{ Ġindex , Ġi Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Should Ġbe Ġthe Ġcorrect Ġchild ", Ġ" some Ġtext Ġ$ i ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( ll . getChild At ( index ) Ġas ĠTextView ). text ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Re compose () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcounter Ġ= ĠCounter () ĊĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠRe compose Test Components A ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcounter , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠClick Action . Re compose ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġeverything Ġgot Ġrendered Ġonce ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 2 "]) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 1 0 0 ) Ġas ĠTextView ). perform Click () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 1 0 2 ) Ġas ĠTextView ). perform Click () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnothing Ġshould Ġhappen Ġsynchronous ly ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 2 "]) ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġonly Ġthe Ġclicked Ġview Ġgot Ġrer ender ed ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" 1 0 2 "]) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġre compose () Ġboth Ġthe Ġparent Ġand Ġthe Ġchild ... Ġand Ġshow Ġthat Ġthe Ġchild Ġonly ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġre comp o ses Ġonce Ġas Ġa Ġresult ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 9 9 ) Ġas ĠLinearLayout ). perform Click () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 1 0 2 ) Ġas ĠTextView ). perform Click () ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġcounter [" 1 0 2 "]) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Root Re compose () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcounter Ġ= ĠCounter () ĊĠĠĠĠĠĠĠ Ġval Ġtrigger Ġ= ĠTrigger () ĊĊĠĠĠĠĠĠĠ Ġval Ġlistener Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠClick Action . Perform On View Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrigger . re compose () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtrigger . subscribe () ĊĠĠĠĠĠĠĠĠĠĠĠ ĠRe compose Test Components A ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcounter , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlistener ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġeverything Ġgot Ġrendered Ġonce ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 2 "]) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 1 0 0 ) Ġas ĠTextView ). perform Click () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 1 0 2 ) Ġas ĠTextView ). perform Click () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnothing Ġshould Ġhappen Ġsynchronous ly ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 , Ġcounter [" 1 0 2 "]) ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġas Ġwe Ġre compose ĠROOT Ġon Ġevery Ġtap , Ġeverything Ġshould Ġbe Ġincreased Ġonce , Ġbecause Ġtwo ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġclicks Ġlay ed Ġto Ġone Ġframe . ĠNone Ġof Ġthese Ġcomponents Ġare Ġsk ipp able , Ġso Ġeach Ġincre ments ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 2 , Ġcounter [" 1 0 2 "]) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 9 9 ) Ġas ĠLinearLayout ). perform Click () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . findViewById ( 1 0 2 ) Ġas ĠTextView ). perform Click () ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġagain , Ġno Ġmatter Ġwhat Ġwe Ġt apped , Ġwe Ġwant Ġto Ġre compose Ġroot , Ġso Ġall Ġcounts Ġincreased ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġcounter [" A "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġcounter [" 1 0 0 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġcounter [" 1 0 1 "]) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 3 , Ġcounter [" 1 0 2 "]) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġcomponents Ġfor Ġtesting Ġre compose Ġbehavior Ġabove ĊĠĠĠ Ġsealed Ġclass ĠClick Action Ġ{ ĊĠĠĠĠĠĠĠ Ġobject ĠRe compose Ġ: ĠClick Action () ĊĠĠĠĠĠĠĠ Ġclass ĠPerform On View ( val Ġaction : Ġ( View ) Ġ-> ĠUnit ) Ġ: ĠClick Action () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Composable Ġfun ĠRe compose Test Components B ( counter : ĠCounter , Ġlistener : ĠClick Action , Ġid : ĠInt Ġ= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcounter . inc ("$ id ") ĊĊĠĠĠĠĠĠĠ Ġval Ġre compose Ġ= Ġinvalidate ĊĊĠĠĠĠĠĠĠ ĠTextView ( id Ġ= Ġid , ĠonClick Listener Ġ= ĠView . OnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Suppress (" DE PREC ATION ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( listener ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠClick Action . Re compose Ġ-> Ġre compose () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠClick Action . Perform On View Ġ-> Ġlistener . action . invoke ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Composable Ġfun ĠRe compose Test Components A ( counter : ĠCounter , Ġlistener : ĠClick Action ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcounter . inc (" A ") ĊĠĠĠĠĠĠĠ Ġval Ġre compose Ġ= Ġinvalidate ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout ( id Ġ= Ġ 9 9 , ĠonClick Listener Ġ= ĠView . OnClickListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Suppress (" DE PREC ATION ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( listener ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠClick Action . Re compose Ġ-> Ġre compose () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠClick Action . Perform On View Ġ-> Ġlistener . action . invoke ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( id Ġin Ġ 1 0 0 .. 1 0 2 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkey ( id ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠRe compose Test Components B ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcounter , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlistener , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Correct View Tree () Ġ{ ĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġassert Child Hierarchy ( activity . root ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Correct View Tree With Components () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun ĠB () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTextView () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ Ġactivity Ġ-> ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġassert Child Hierarchy ( activity . root ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< TextView Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< TextView Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Correct View Tree With Component With Multiple Roots () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun ĠB () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTextView () ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTextView () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLinearLayout Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġassert Child Hierarchy ( activity . root ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< TextView Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< TextView Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< TextView Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ< TextView Ġ/> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ</ LinearLayout > ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test Ġ// Ġregression Ġb / 1 5 7 1 1 1 2 7 1 ĊĠĠĠ Ġfun Ġtest Insert During Re composition () Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġinclude A Ġby Ġmutable State Of ( false ) ĊĠĠĠĠĠĠĠ Ġvar Ġsome State Ġby Ġmutable State Of ( 0 ) ĊĠĠĠĠĠĠĠ Ġvar Ġsome Other State Ġby Ġmutable State Of ( 1 ) ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun ĠB (@ Suppress (" UNUSED _ PARAMETER ") Ġvalue : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġempty ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun ĠA () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠB ( some State ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsome State ++ ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun ĠT () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsub Compose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTake Ġup Ġsome Ġslot Ġspace ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThis Ġmakes Ġit Ġmore Ġlikely Ġto Ġreproduce Ġbug Ġ 1 5 7 1 1 1 2 7 1 . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremember ( 1 , Ġ 2 , Ġ 3 , Ġ 4 , Ġ 5 , Ġ 6 , Ġ 7 , Ġ 8 , Ġ 9 , Ġ 1 0 , Ġ 1 1 , Ġ 1 2 , Ġ 1 3 , Ġ 1 4 , Ġ 1 5 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( include A ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠWrapper Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB ( some Other State ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB ( 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB ( 3 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB ( 4 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠA () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠT () ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinclude A Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsome Other State Ġ= Ġ 1 0 ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġforce Ġre compose ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test Ġ// Ġregression Ġtest Ġfor Ġb / 1 6 1 8 9 2 0 1 6 ĊĠĠĠ Ġfun Ġtest Multiple Re compose () Ġ{ ĊĠĠĠĠĠĠĠ Ġclass ĠA ĊĊĠĠĠĠĠĠĠ Ġvar Ġstate 1 Ġby Ġmutable State Of ( 1 ) ĊĠĠĠĠĠĠĠ Ġvar Ġstate 2 Ġby Ġmutable State Of ( 1 ) ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun Ġvalidate ( a : ĠA ?) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertNotNull ( a ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun Ġuse (@ Suppress (" UNUSED _ PARAMETER ") Ġi : ĠInt ) Ġ{ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun Ġuse A ( a : ĠA Ġ= ĠA ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalidate ( a ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuse ( state 2 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Composable Ġfun Ġtest () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuse ( state 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuse A () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtest () ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠRe compose Ġtest () Ġskipping Ġuse A () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate 1 Ġ= Ġ 2 ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠRe compose Ġuse A (). ĠIn Ġthe Ġbug Ġthis Ġcauses Ġvalidate () Ġto Ġbe Ġpassed Ġa Ġnull Ġbecause ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthe Ġre compose Ġscope Ġis Ġupdated Ġwith Ġa Ġlambda Ġthat Ġcaptures Ġthe Ġparameters Ġwhen Ġthe ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġdefault Ġparameter Ġexpressions Ġare Ġskipped . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate 2 Ġ= Ġ 2 ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġforce Ġre compose Ġto Ġvalidate Ġa . ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġ@ Opt In ( Experimental Compose Api :: class ) ĊĠĠĠ Ġfun Ġtest Frame Transition () Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġsnapshot Id : ĠInt ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġcompose Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsnapshot Id Ġ= Ġcurrent Snapshot (). id ĊĠĠĠĠĠĠĠ Ġ}. then Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġassert Not Same ( snapshot Id , Ġcurrent Snapshot (). id ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Composable Ċ fun ĠWrapper ( children : Ġ@ Composable Ġ() Ġ-> ĠUnit ) Ġ{ ĊĠĠĠ Ġchildren () Ċ } Ċ Ċ fun Ġassert Child Hierarchy ( root : ĠViewGroup , Ġget Hierarchy : Ġ() Ġ-> ĠString ) Ġ{ ĊĠĠĠ Ġval Ġreal Hierarchy Ġ= Ġprint Child Hierarchy ( root ) ĊĊĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠ Ġnormalize String ( get Hierarchy ()), ĊĠĠĠĠĠĠĠ Ġreal Hierarchy . trim () ĊĠĠĠ Ġ) Ċ } Ċ Ċ fun Ġnormalize String ( str : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġval Ġlines Ġ= Ġstr . split ('\ n '). drop While Ġ{ Ġit . isBlank () Ġ}. drop Last While Ġ{ ĊĠĠĠĠĠĠĠ Ġit . isBlank () ĊĠĠĠ Ġ} ĊĠĠĠ Ġif Ġ( lines . isEmpty ()) Ġreturn Ġ"" ĊĠĠĠ Ġval Ġto Remove Ġ= Ġlines . first (). take While Ġ{ Ġit Ġ== Ġ' Ġ' Ġ}. length ĊĠĠĠ Ġreturn Ġlines . join ToString ("\ n ") Ġ{ Ġit . substring ( Math . min ( to Remove , Ġit . length )) Ġ} Ċ } Ċ Ċ fun Ġprint Child Hierarchy ( root : ĠViewGroup ): ĠString Ġ{ ĊĠĠĠ Ġval Ġsb Ġ= ĠStringBuilder () ĊĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġroot . child Count ) Ġ{ ĊĠĠĠĠĠĠĠ Ġprint View ( root . getChild At ( i ), Ġ 0 , Ġsb ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġsb . toString () Ċ } Ċ Ċ fun Ġprint View ( view : ĠView , Ġindent : ĠInt , Ġsb : ĠStringBuilder ) Ġ{ ĊĠĠĠ Ġval Ġwhitespace Ġ= Ġ" Ġ". repeat ( indent ) ĊĠĠĠ Ġval Ġname Ġ= Ġview . java Class . simple Name ĊĠĠĠ Ġval Ġattributes Ġ= Ġprint Attributes ( view ) ĊĠĠĠ Ġif Ġ( view Ġis ĠViewGroup Ġ&& Ġview . child Count Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġsb . append Line ("$ whitespace <$ name $ attributes >") ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġview . child Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprint View ( view . getChild At ( i ), Ġindent Ġ+ Ġ 4 , Ġsb ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġsb . append Line ("$ whitespace </ $ name >") ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġsb . append Line ("$ whitespace <$ name $ attributes Ġ/> ") ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġprint Attributes ( view : ĠView ): ĠString Ġ{ ĊĠĠĠ Ġval Ġattrs Ġ= Ġmutable ListOf < String >() ĊĊĠĠĠ Ġ// ĠNOTE : Ġright Ġnow Ġwe Ġonly Ġlook Ġfor Ġid Ġand Ġtext Ġas Ġattributes Ġto Ġprint Ġout ... Ġbut Ġwe Ġare ĊĠĠĠ Ġ// Ġfree Ġto Ġadd Ġmore Ġif Ġit Ġmakes Ġsense ĊĠĠĠ Ġif Ġ( view . id Ġ!= Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġattrs . add (" id =${ view . id }") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ( view Ġis ĠTextView Ġ&& Ġview . text . length Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġattrs . add (" text =' ${ view . text }' ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġresult Ġ= Ġattrs . join ToString (" Ġ", Ġprefix Ġ= Ġ" Ġ") ĊĠĠĠ Ġif Ġ( result . length Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ"" ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġresult Ċ } Ċ Ċ class ĠCounter Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġcounts Ġ= Ġmutable Map Of < String , ĠInt >() ĊĠĠĠ Ġfun Ġinc ( key : ĠString ) Ġ= Ġcounts . get Or Put ( key , Ġ{ Ġ 0 Ġ}). let Ġ{ Ġcounts [ key ] Ġ= Ġit Ġ+ Ġ 1 Ġ} ĊĠĠĠ Ġfun Ġreset () Ġ{ ĊĠĠĠĠĠĠĠ Ġcounts Ġ= Ġmutable Map Of () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoperator Ġfun Ġget ( key : ĠString ) Ġ= Ġcounts [ key ] Ġ?: Ġ 0 Ċ } Ċ