package Ġcom . so yle . stories . pro se . pro se Editor Ċ Ċ import Ġcom . so yle . stories . common .* Ċ import Ġcom . so yle . stories . common . EntityId . Companion . as Id Of Ċ import Ġcom . so yle . stories . entities .* Ċ import Ġcom . so yle . stories . gui . View Ċ import Ġcom . so yle . stories . pro se . Content Re placed Ċ import Ġcom . so yle . stories . pro se . Text Inserted Into Pro se Ċ import Ġcom . so yle . stories . pro se . edit Pro se . Edit Pro se Controller Ċ import Ġcom . so yle . stories . pro se . read Pro se . Read Pro se Controller Ċ import Ġcom . so yle . stories . pro se . use cases . read Pro se . Read Pro se Ċ import Ġcom . so yle . stories . scene . use cases . get Story Elements To Mention . Get Story Elements To Mention In Scene Ċ import Ġkotlinx . coroutines .* Ċ import Ġorg . junit . jupiter . api . Assertions .* Ċ import Ġorg . junit . jupiter . api . Nested Ċ import Ġorg . junit . jupiter . api . Test Ċ import Ġkotlin . reflect . K Function Ċ Ċ class Ġ` Pro se ĠEditor ĠController ĠUnit ĠTest ` Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġpro se Id Ġ= ĠPro se . Id () ĊĠĠĠ Ġprivate Ġvar ĠviewModel : ĠPro se Editor ViewModel ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġval Ġview Ġ= Ġobject Ġ: ĠView . Nullable < Pro se Editor ViewModel > Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ@ Synchron ized ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġupdate ( update : ĠPro se Editor ViewModel ?. () Ġ-> ĠPro se Editor ViewModel ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ ` Pro se ĠEditor ĠController ĠUnit ĠTest `. viewModel Ġ= ĠviewModel . update () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Synchron ized ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġupdate Or Invalid ated ( update : ĠPro se Editor ViewModel . () Ġ-> ĠPro se Editor ViewModel ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ ` Pro se ĠEditor ĠController ĠUnit ĠTest `. viewModel Ġ= ĠviewModel ?. update () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġval ĠviewModel : ĠPro se Editor ViewModel ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġthis @ ` Pro se ĠEditor ĠController ĠUnit ĠTest `. viewModel ĊĠĠĠ Ġ} ĊĠĠĠ Ġprivate Ġval Ġread Pro se Controller Ġ= Ġobject Ġ: ĠRead Pro se Controller Ġ{ ĊĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġpro se Revision Number Ġ= Ġ 0 L ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġpro se Body Ġ= Ġ"" ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġpro se Ment ions Ġ= ĠlistOf < Pro se Mention <* >>() ĊĊĠĠĠĠĠĠĠ Ġfun Ġgiven Pro se Revision Number ( revision : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpro se Revision Number Ġ= Ġrevision ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġgiven Pro se Body ( body : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpro se Body Ġ= Ġbody ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġgiven Pro se Ment ions ( mentions : ĠList < Pro se Mention <* >>) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpro se Ment ions Ġ= Ġmentions ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġread Pro se ( pro se Id : ĠPro se . Id , Ġreceiver : ĠRead Pro se . Output Port ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreceiver . receive Pro se ( Read Pro se . Response Model ( pro se Id , Ġpro se Revision Number , Ġpro se Body , Ġpro se Ment ions )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġprivate Ġval Ġedit Pro se Controller Ġ= Ġobject Ġ: ĠEdit Pro se Controller Ġ{ ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġcall Log Ġ= Ġmutable Map Of < K Function <* >, ĠMap < String , ĠAny ? >>() ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġcall Jobs Ġ= Ġmutable Map Of < K Function <* >, ĠComp letable Job >() ĊĠĠĠĠĠĠĠ Ġfun Ġget Call ( function : ĠK Function < *> ): ĠMap < String , ĠAny ?> Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcall Log [ function ] Ġ?: Ġthrow ĠAssertionError ("$ function Ġwas Ġnot Ġcalled ") ĊĊĠĠĠĠĠĠĠ Ġfun Ġcomplete Call ( function : ĠK Function <* >, Ġexception : ĠThrowable ? Ġ= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjob Ġ= Ġcall Jobs [ function ] Ġ?: Ġthrow ĠAssertionError ("$ function Ġwas Ġnot Ġcalled ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( exception Ġ== Ġnull ) Ġjob . complete () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġjob . complete Exception ally ( exception ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġupdate Pro se ( pro se Id : ĠPro se . Id , Ġcontent : ĠList < Pro se Content >): ĠJob Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjob Ġ= ĠJob () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcall Jobs [ Edit Pro se Controller :: update Pro se ] Ġ= Ġjob ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcall Log [ Edit Pro se Controller :: update Pro se ] Ġ= Ġmap Of (" pro se Id " Ġto Ġpro se Id , Ġ" content " Ġto Ġcontent ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġjob ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġprivate Ġval Ġpotential Ment ions Loader Ġ= Ġobject Ġ: Ġ( Non Blank String , ĠOn Load Mention Query Output ) Ġ-> ĠUnit Ġ{ ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġoptions Ġ= Ġmutable ListOf < Get Story Elements To Mention In Scene . Matching Story Element >() ĊĊĠĠĠĠĠĠĠ Ġfun Ġgiven Mention Option ( entityId : ĠEntity Id <* >, Ġname : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoptions . add ( Get Story Elements To Mention In Scene . Matching Story Element ( entityId , Ġname )) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġinvoke ( query : ĠNon Blank String , Ġoutput : ĠOn Load Mention Query Output ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput . invoke ( options . filter Ġ{ Ġit . name . contains ( query , Ġignore Case Ġ= Ġtrue ) Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġprivate Ġval Ġcontroller Ġ= ĠPro se Editor Controller ( ĊĠĠĠĠĠĠĠ Ġpro se Id , ĊĠĠĠĠĠĠĠ Ġview , ĊĠĠĠĠĠĠĠ Ġread Pro se Controller , ĊĠĠĠĠĠĠĠ Ġedit Pro se Controller , ĊĠĠĠĠĠĠĠ Ġpotential Ment ions Loader ĊĠĠĠ Ġ) Ġ{} ĊĊĠĠĠ Ġ@ Nested ĊĠĠĠ Ġinner Ġclass Ġ` When ĠState Ġis ĠInvalid ated ` Ġ{ ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġbob Id Ġ= ĠCharacter . Id (). as Id Of ( Character :: class ) ĊĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Pro se Controller . given Pro se Revision Number ( 4 2 L ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Pro se Controller . given Pro se Body (" I 'm Ġthe Ġpro se Ġbody \ n that Ġmentions ĠBob , Ġthe Ġcharacter Ġand \ n starts Ġanother Ġline ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Pro se Controller . given Pro se Ment ions ( listOf ( Pro se Mention ( bob Id , ĠPro se Mention Range ( 3 3 , Ġ 3 )))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` should Ġread Ġpro se `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 4 2 L , Ġit . version Number ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" I 'm Ġthe Ġpro se Ġbody \ n that Ġmentions "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" Bob ", Ġbob Id ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (", Ġthe Ġcharacter Ġand \ n starts Ġanother Ġline ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), Ġit . content ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` should Ġhandle Ġmentions Ġup Ġagainst Ġend Ġof Ġbody `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfr ank Id Ġ= ĠCharacter . Id (). as Id Of ( Character :: class ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Pro se Controller . given Pro se Body (" I 'm Ġthe Ġpro se Ġbody Ġthat Ġmentions ĠBob , Ġand ĠFrank ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Pro se Controller . given Pro se Ment ions ( listOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Mention ( bob Id , ĠPro se Mention Range ( 3 3 , Ġ 3 )), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Mention ( fr ank Id , ĠPro se Mention Range ( 4 2 , Ġ 5 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 4 2 L , Ġit . version Number ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" I 'm Ġthe Ġpro se Ġbody Ġthat Ġmentions Ġ"), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" Bob ", Ġbob Id ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (", Ġand Ġ"), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" Fr ank ", Ġfr ank Id ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), Ġit . content ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Nested ĊĠĠĠ Ġinner Ġclass Ġ` Text ĠInsert ed ĠEvent ĠReceived ` Ġ{ ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġbob Id Ġ= ĠCharacter . Id (). as Id Of ( Character :: class ) ĊĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Pro se Controller . given Pro se Body (" Starting Ġcontent ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` should Ġupdate Ġversion Ġnumber Ġand Ġtext `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . receive Content Re placed Event ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContent Re placed ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se . build ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpro se Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" I 'm Ġthe Ġpro se Ġbody Ġthat Ġmentions ĠBob , Ġthe Ġcharacter ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( Pro se Mention ( bob Id , ĠPro se Mention Range ( 3 3 , Ġ 3 ))), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 L ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" I 'm Ġthe Ġpro se Ġbody Ġthat Ġmentions Ġ"), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" Bob ", Ġbob Id ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (", Ġthe Ġcharacter ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), Ġit . content ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` wrong Ġpro se Ġid Ġevent Ġshould Ġhave Ġno Ġeffect `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . receive Content Re placed Event ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContent Re placed ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se . build ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se . Id (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" I 'm Ġthe Ġpro se Ġbody Ġthat Ġmentions ĠBob , Ġthe Ġcharacter ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( Pro se Mention ( bob Id , ĠPro se Mention Range ( 3 3 , Ġ 3 ))), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 L ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 0 L , Ġit . version Number ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" Starting Ġcontent ", Ġit . content . single (). text ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Nested ĊĠĠĠ Ġinner Ġclass Ġ` Select ĠStory ĠElement Ġfrom ĠQuery ĠList ` Ġ{ ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġbil ly Id Ġ= ĠEntity Id . of ( Character :: class ). id ( Character . Id ()) ĊĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` should Ġadd Ġnew Ġmention Ġto Ġview Ġmodel Ġand Ġremove Ġ@ Ġsymbol `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("@ "))) Ġ} Ġ// Ġsimulate Ġview Ġtyping Ġthe Ġ@ Ġsymbol ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . prime Mention Query ( 0 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpotential Ment ions Loader . given Mention Option ( EntityId . of ( Character :: class ). id ( Character . Id ()), Ġ" Bob ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpotential Ment ions Loader . given Mention Option ( bil ly Id , Ġ" B illy ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpotential Ment ions Loader . given Mention Option ( EntityId . of ( Character :: class ). id ( Character . Id ()), Ġ" Bo yd ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("@ B "))) Ġ} Ġ// Ġsimulate Ġview Ġtyping ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Story Elements Containing ( Non Blank String . create (" B ") !! ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . select Story Element ( 1 , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( Mention (" B illy ", Ġbil ly Id )), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. content ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` should Ġonly Ġreplace Ġcontent Ġin Ġquery `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text (" Let 's Ġtalk Ġabout Ġ Ġbecause Ġhe 's Ġcool "))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text (" Let 's Ġtalk Ġabout Ġ@ Ġbecause Ġhe 's Ġcool "))) Ġ} Ġ// Ġsimulate Ġview Ġtyping Ġthe Ġ@ Ġsymbol ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . prime Mention Query ( 1 7 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpotential Ment ions Loader . given Mention Option ( EntityId . of ( Character :: class ). id ( Character . Id ()), Ġ" Bob ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpotential Ment ions Loader . given Mention Option ( bil ly Id , Ġ" B illy ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpotential Ment ions Loader . given Mention Option ( EntityId . of ( Character :: class ). id ( Character . Id ()), Ġ" Bo yd ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text (" Let 's Ġtalk Ġabout Ġ@ B Ġbecause Ġhe 's Ġcool "))) Ġ} Ġ// Ġsimulate Ġview Ġtyping ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Story Elements Containing ( Non Blank String . create (" B ") !! ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . select Story Element ( 1 , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" Let 's Ġtalk Ġabout Ġ"), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" B illy ", Ġbil ly Id ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" Ġbecause Ġhe 's Ġcool ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. content ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Nested ĊĠĠĠ Ġinner Ġclass Ġ` Save ` Ġ{ ĊĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Pro se Controller . given Pro se Body (" Starting Ġcontent ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` should Ġupdate Ġview Ġmodel Ġcontent Ġimmediately `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("${ content . single (). text } Ġwith "))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 0 L , Ġit . version Number ) Ġ// Ġshould Ġnot Ġhave Ġupdated Ġversion Ġnumber Ġyet ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" Starting Ġcontent Ġwith ", Ġit . content . single (). text ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠ Ġfun Ġ` when Ġassociated Ġevent Ġis Ġreturned , Ġshould Ġonly Ġupdate Ġversion Ġnumber `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("${ content . single (). text } Ġwith "))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . receive Content Re placed Event ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContent Re placed ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se . build ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpro se Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Starting Ġcontent Ġwith ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 L ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠviewModel !!. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( 1 L , Ġit . version Number ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" Starting Ġcontent Ġwith ", Ġit . content . single (). text ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Nested ĊĠĠĠĠĠĠĠ Ġinner Ġclass Ġ` call Ġedit Ġpro se Ġcontroller ` Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġ` No Ġmention Ġshould Ġsend Ġthe Ġentire Ġcontent Ġstring `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("${ content . single (). text } Ġwith "))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdate Pro se Call Ġ= Ġedit Pro se Controller . get Call ( Edit Pro se Controller :: update Pro se ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( pro se Id , Ġupdate Pro se Call . getValue (" pro se Id ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Content (" Starting Ġcontent Ġwith ", Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), Ġupdate Pro se Call . getValue (" content ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġ` adjacent Ġbasic Ġtext Ġblocks Ġshould Ġbe Ġjoined Ġwith Ġa Ġnewline Ġcharacter `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbob Id Ġ= ĠCharacter . Id (). as Id Of ( Character :: class ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" Starting Ġcontent Ġwith "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" another Ġline Ġof Ġtext Ġthat Ġmentions Ġ"), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" Bob ", Ġbob Id ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" Ġand Ġthen Ġhas "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" another Ġline Ġof Ġtext Ġafter ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ)) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdate Pro se Call Ġ= Ġedit Pro se Controller . get Call ( Edit Pro se Controller :: update Pro se ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( pro se Id , Ġupdate Pro se Call . getValue (" pro se Id ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Content (" Starting Ġcontent Ġwith \ nan other Ġline Ġof Ġtext Ġthat Ġmentions Ġ", Ġbob Id Ġto Ġcount Lines (" Bob ") Ġas ĠSingle Line ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Content (" Ġand Ġthen Ġhas \ nan other Ġline Ġof Ġtext Ġafter ", Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), Ġupdate Pro se Call . getValue (" content ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġ` should Ġlock Ġinput Ġuntil Ġevent Ġis Ġreceived `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("${ content . single (). text } Ġwith "))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertTrue ( viewModel !!. is Locked ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġ` should Ġunlock Ġwhen Ġevent Ġis Ġreceived `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("${ content . single (). text } Ġwith "))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . receive Content Re placed Event ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContent Re placed ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se . build ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpro se Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Starting Ġcontent Ġwith ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 L ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( viewModel !!. is Locked ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġ` unlock Ġif Ġfailed Ġto Ġsave `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ Ġcopy ( content Ġ= ĠlistOf ( Basic Text ("${ content . single (). text } Ġwith "))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġedit Pro se Controller . complete Call ( Edit Pro se Controller :: update Pro se , Ġobject Ġ: ĠSo yle St ories Exception () Ġ{}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertFalse ( viewModel !!. is Locked ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġ` Should Ġbreak Ġup Ġcontent Ġby Ġmentions `() Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . get Valid State () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcharacter EntityId Ġ= ĠEntity Id . of ( Character :: class ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbob Id Ġ= ĠCharacter . Id () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfr ank Id Ġ= ĠCharacter . Id () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġview . update Or Invalid ated Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcopy ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontent Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" Bob ", Ġcharacter EntityId . id ( bob Id )), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" Ġis Ġannoying , Ġbut Ġ"), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠM ention (" Fr ank ", Ġcharacter EntityId . id ( fr ank Id )), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠBasic Text (" Ġthink s Ġhe 's Ġfine .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontroller . save () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdate Pro se Call Ġ= Ġedit Pro se Controller . get Call ( Edit Pro se Controller :: update Pro se ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( pro se Id , Ġupdate Pro se Call . getValue (" pro se Id ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Content ("", Ġcharacter EntityId . id ( bob Id ) Ġto Ġcount Lines (" Bob ") Ġas ĠSingle Line ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Content ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġis Ġannoying , Ġbut Ġ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcharacter EntityId . id ( fr ank Id ) Ġto Ġcount Lines (" Fr ank ") Ġas ĠSingle Line ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro se Content (" Ġthink s Ġhe 's Ġfine .", Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), Ġupdate Pro se Call . getValue (" content ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġtext Inserted Into Pro se ( ĊĠĠĠĠĠĠĠ Ġrevision : ĠLong , ĊĠĠĠĠĠĠĠ Ġinserted Text : ĠString , ĊĠĠĠĠĠĠĠ Ġindex : ĠInt , ĊĠĠĠĠĠĠĠ Ġpro se Id : ĠPro se . Id Ġ= Ġthis . pro se Id ĊĠĠĠ Ġ) Ġ= ĊĠĠĠĠĠĠĠ ĠText Inserted Into Pro se ( Pro se . build ( pro se Id , Ġ"", ĠlistOf (), Ġrevision ), Ġinserted Text , Ġindex ) Ċ Ċ }