package Ġcom . tester um . web _ backend . services . save Ċ Ċ import Ġcom . tester um . file _ service . file . Resource File Service Ċ import Ġcom . tester um . file _ service . util . is Changed Re qu iring Save Ċ import Ġcom . tester um . file _ service . util . is Step Pattern Change Compatible Ċ import Ġcom . tester um . model . arg . Arg Ċ import Ġcom . tester um . model . exception . ValidationException Ċ import Ġcom . tester um . model . feature . Feature Ċ import Ġcom . tester um . model . resources . Resource Context Ċ import Ġcom . tester um . model . step . Comp osed Step Def Ċ import Ġcom . tester um . model . step . Step Call Ċ import Ġcom . tester um . model . test . Test Model Ċ import Ġcom . tester um . model . text . Step Pattern Ċ import Ġcom . tester um . test _ file _ format . step def . signature . File Step Def Signature Parser Factory Ċ import Ġcom . tester um . web _ backend . services . project . Web Project Manager Ċ import Ġcom . tester um . web _ backend . util . is Other Step With The Same Step Pattern As The New Ċ import Ġcom . tester um . web _ backend . util . is Step Pattern Used Ċ Ċ class ĠSave Frontend Service ( private Ġval Ġweb Project Manager : ĠWeb Project Manager , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġresource File Service : ĠResource File Service ) Ġ{ ĊĊĠĠĠ Ġprivate Ġfun Ġsteps Cache () Ġ= Ġweb Project Manager . getProject Services (). get Steps Cache () ĊĊĠĠĠ Ġprivate Ġfun Ġget Resources Dir () Ġ= Ġweb Project Manager . getProject Services (). dirs (). getResources Dir () ĊĊĠĠĠ Ġfun Ġsave Feature ( feature : ĠFeature , Ġrecursive Save : ĠBoolean Ġ= Ġtrue ): ĠFeature Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( recursive Save ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Step Calls Re cursively ( feature . hooks . before All ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Step Calls Re cursively ( feature . hooks . before Each ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Step Calls Re cursively ( feature . hooks . after Each ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Step Calls Re cursively ( feature . hooks . after All ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġfeature To Save Ġ= Ġif Ġ( recursive Save ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Feature External Resources ( feature ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġfeatures Dir Ġ= Ġweb Project Manager . getProject Services (). dirs (). get Features Dir () ĊĊĠĠĠĠĠĠĠ Ġval Ġsaved Feature Ġ= Ġweb Project Manager . getProject Services (). get Feature Cache (). save ( feature To Save , Ġfeatures Dir ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġif Ġthe Ġfeature Ġwas Ġrenamed , Ġnotify Ġtests Ġcache ĊĠĠĠĠĠĠĠ Ġval Ġold Path Ġ= Ġfeature To Save . old Path ĊĠĠĠĠĠĠĠ Ġval Ġnew Path Ġ= Ġsaved Feature . path ĊĠĠĠĠĠĠĠ Ġif Ġ( old Path Ġ!= Ġnull Ġ&& Ġnew Path Ġ!= Ġold Path ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġweb Project Manager . reload Project () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( feature To Save . hooks . has Hooks ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġre initialize Caches () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsaved Feature ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Test ( test : ĠTest Model ): ĠTest Model Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsaved Test Ġ= Ġsave Test Without Re initial izing Caches ( test ) ĊĊĠĠĠĠĠĠĠ Ġre initialize Caches () ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsaved Test ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Test Without Re initial izing Caches ( test : ĠTest Model , Ġrecursive Save : ĠBoolean Ġ= Ġtrue ): ĠTest Model Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( recursive Save ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Step Calls Re cursively ( test . step Calls ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Step Calls Re cursively ( test . after Hooks ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġtest To Save Ġ= Ġif Ġ( recursive Save ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Test External Resources ( test ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtest ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġweb Project Manager . getProject Services (). get Tests Cache (). save ( test To Save ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Comp osed Step ( composed Step : ĠComp osed Step Def ): ĠComp osed Step Def Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsaved Step Ġ= Ġsave Comp osed Step Without Re initial izing Caches ( composed Step ) ĊĊĠĠĠĠĠĠĠ Ġre initialize Caches () ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsaved Step ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Comp osed Step Without Re initial izing Caches ( composed Step : ĠComp osed Step Def , Ġrecursive Save : ĠBoolean Ġ= Ġtrue ): ĠComp osed Step Def Ġ{ ĊĠĠĠĠĠĠĠ Ġvalidate Comp osed Step Save ( composed Step ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( recursive Save ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Step Calls Re cursively ( composed Step . step Calls ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġstep To Save : ĠComp osed Step Def Ġ= Ġif Ġ( recursive Save ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave External Resources ( composed Step ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcomposed Step ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġexisting Step Ġ= Ġstep To Save . old Path ?. let Ġ{ Ġsteps Cache (). get Comp osed Step At Path ( it ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġsaved Comp osed Step Ġ= Ġsteps Cache (). save Comp osed Step ( step To Save ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġupdate Ġaffected Ġtests Ġ& Ġsteps ĊĠĠĠĠĠĠĠ Ġif Ġ( existing Step Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( composed Step . is Changed Re qu iring Save ( existing Step )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexisting Step Pattern Ġ= Ġexisting Step . step Pattern ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Step Pattern Ġ= Ġsaved Comp osed Step . step Pattern ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( existing Step Pattern . is Step Pattern Change Compatible ( new Step Pattern )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Features That Use Old Step ( existing Step , Ġsaved Comp osed Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Tests That Use Old Step ( existing Step , Ġsaved Comp osed Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Steps That Uses Old Step ( existing Step , Ġsaved Comp osed Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsaved Comp osed Step ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Features That Use Old Step ( old Step : ĠComp osed Step Def , Ġnew Step : ĠComp osed Step Def ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfeatures That Uses Old Step Ġ= Ġfind Features That Call ( old Step . step Pattern ) ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( feature ToUpdate Ġin Ġfeatures That Uses Old Step ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġupdated Feature Ġ= Ġfeature ToUpdate ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġstep Call ) Ġin Ġfeature ToUpdate . hooks . before All . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . step Def . step Pattern Ġ== Ġold Step . step Pattern ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Feature Ġ= Ġupdate Step Pattern For Feature Before All Hooks ( updated Feature , Ġindex , Ġnew Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġstep Call ) Ġin Ġfeature ToUpdate . hooks . before Each . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . step Def . step Pattern Ġ== Ġold Step . step Pattern ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Feature Ġ= Ġupdate Step Pattern For Feature BeforeEach Hooks ( updated Feature , Ġindex , Ġnew Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġstep Call ) Ġin Ġfeature ToUpdate . hooks . after Each . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . step Def . step Pattern Ġ== Ġold Step . step Pattern ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Feature Ġ= Ġupdate Step Pattern For Feature After Each Hooks ( updated Feature , Ġindex , Ġnew Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġstep Call ) Ġin Ġfeature ToUpdate . hooks . after All . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . step Def . step Pattern Ġ== Ġold Step . step Pattern ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Feature Ġ= Ġupdate Step Pattern For Feature After All Hooks ( updated Feature , Ġindex , Ġnew Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Feature ( updated Feature , Ġrecursive Save Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġfind Features That Call ( sear ched Step Pattern : ĠStep Pattern ): ĠList < Feature > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult : ĠMutable List < Feature > Ġ= Ġmutable ListOf () ĊĊĠĠĠĠĠĠĠ Ġval Ġall Features Ġ= Ġweb Project Manager . getProject Services (). get Feature Cache (). getAll Features () ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( feature Ġin Ġall Features ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( feature . hooks . before All . is Step Pattern Used ( sear ched Step Pattern )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( feature ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( feature . hooks . before Each . is Step Pattern Used ( sear ched Step Pattern )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( feature ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( feature . hooks . after Each . is Step Pattern Used ( sear ched Step Pattern )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( feature ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( feature . hooks . after All . is Step Pattern Used ( sear ched Step Pattern )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( feature ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Step Pattern For Feature Before All Hooks ( feature ToUpdate : ĠFeature , Ġstep Call Index ToUpdate : ĠInt , Ġnew Step : ĠComp osed Step Def ): ĠFeature Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdated Calls Ġ= Ġfeature ToUpdate . hooks . before All . to Mutable List () ĊĠĠĠĠĠĠĠ Ġupdated Calls [ step Call Index ToUpdate ] Ġ= Ġupdated Calls [ step Call Index ToUpdate ]. copy ( step Def Ġ= Ġnew Step ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġfeature ToUpdate . copy ( hooks Ġ= Ġfeature ToUpdate . hooks . copy ( before All Ġ= Ġupdated Calls )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Step Pattern For Feature BeforeEach Hooks ( feature ToUpdate : ĠFeature , Ġstep Call Index ToUpdate : ĠInt , Ġnew Step : ĠComp osed Step Def ): ĠFeature Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdated Calls Ġ= Ġfeature ToUpdate . hooks . before Each . to Mutable List () ĊĠĠĠĠĠĠĠ Ġupdated Calls [ step Call Index ToUpdate ] Ġ= Ġupdated Calls [ step Call Index ToUpdate ]. copy ( step Def Ġ= Ġnew Step ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġfeature ToUpdate . copy ( hooks Ġ= Ġfeature ToUpdate . hooks . copy ( before Each Ġ= Ġupdated Calls )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Step Pattern For Feature After Each Hooks ( feature ToUpdate : ĠFeature , Ġstep Call Index ToUpdate : ĠInt , Ġnew Step : ĠComp osed Step Def ): ĠFeature Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdated Calls Ġ= Ġfeature ToUpdate . hooks . after Each . to Mutable List () ĊĠĠĠĠĠĠĠ Ġupdated Calls [ step Call Index ToUpdate ] Ġ= Ġupdated Calls [ step Call Index ToUpdate ]. copy ( step Def Ġ= Ġnew Step ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġfeature ToUpdate . copy ( hooks Ġ= Ġfeature ToUpdate . hooks . copy ( after Each Ġ= Ġupdated Calls )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Step Pattern For Feature After All Hooks ( feature ToUpdate : ĠFeature , Ġstep Call Index ToUpdate : ĠInt , Ġnew Step : ĠComp osed Step Def ): ĠFeature Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdated Calls Ġ= Ġfeature ToUpdate . hooks . after All . to Mutable List () ĊĠĠĠĠĠĠĠ Ġupdated Calls [ step Call Index ToUpdate ] Ġ= Ġupdated Calls [ step Call Index ToUpdate ]. copy ( step Def Ġ= Ġnew Step ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġfeature ToUpdate . copy ( hooks Ġ= Ġfeature ToUpdate . hooks . copy ( after All Ġ= Ġupdated Calls )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Tests That Use Old Step ( old Step : ĠComp osed Step Def , Ġnew Step : ĠComp osed Step Def ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtests That Uses Old Step Ġ= Ġfind Tests That Call ( old Step . step Pattern ) ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( test ToUpdate Ġin Ġtests That Uses Old Step ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġupdated Test Ġ= Ġtest ToUpdate ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġstep Call ) Ġin Ġtest ToUpdate . step Calls . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . step Def . step Pattern Ġ== Ġold Step . step Pattern ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Test Ġ= Ġupdate Step Pattern At Step Call For Test ( updated Test , Ġindex , Ġnew Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġstep Call ) Ġin Ġtest ToUpdate . after Hooks . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . step Def . step Pattern Ġ== Ġold Step . step Pattern ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Test Ġ= Ġupdate Step Pattern At After Hook For Test ( updated Test , Ġindex , Ġnew Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Test Without Re initial izing Caches ( updated Test , Ġrecursive Save Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġfind Tests That Call ( sear ched Step Pattern : ĠStep Pattern ): ĠList < Test Model > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult : ĠMutable List < Test Model > Ġ= Ġmutable ListOf () ĊĊĠĠĠĠĠĠĠ Ġval Ġall Tests Ġ= Ġweb Project Manager . getProject Services (). get Tests Cache (). getAll Tests () ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( test Ġin Ġall Tests ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( test . step Calls . is Step Pattern Used ( sear ched Step Pattern )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( test ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( test . after Hooks . is Step Pattern Used ( sear ched Step Pattern )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( test ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Step Pattern At Step Call For Test ( test ToUpdate : ĠTest Model , Ġstep Call Index ToUpdate : ĠInt , Ġnew Step : ĠComp osed Step Def ): ĠTest Model Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdated Calls Ġ= Ġtest ToUpdate . step Calls . to Mutable List () ĊĠĠĠĠĠĠĠ Ġupdated Calls [ step Call Index ToUpdate ] Ġ= Ġupdated Calls [ step Call Index ToUpdate ]. copy ( step Def Ġ= Ġnew Step ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtest ToUpdate . copy ( step Calls Ġ= Ġupdated Calls ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Step Pattern At After Hook For Test ( test ToUpdate : ĠTest Model , Ġstep Call Index ToUpdate : ĠInt , Ġnew Step : ĠComp osed Step Def ): ĠTest Model Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdated After Hook Ġ= Ġtest ToUpdate . after Hooks . to Mutable List () ĊĠĠĠĠĠĠĠ Ġupdated After Hook [ step Call Index ToUpdate ] Ġ= Ġupdated After Hook [ step Call Index ToUpdate ]. copy ( step Def Ġ= Ġnew Step ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtest ToUpdate . copy ( after Hooks Ġ= Ġupdated After Hook ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Steps That Uses Old Step ( old Step : ĠComp osed Step Def , Ġnew Step : ĠComp osed Step Def ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsteps That Use Old Step Ġ= Ġfind Steps That Call ( old Step ) ĊĠĠĠĠĠĠĠ Ġfor Ġ( step Def ToUpdate Ġin Ġsteps That Use Old Step ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġupdated Step Def Ġ= Ġstep Def ToUpdate ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġstep Call ) Ġin Ġstep Def ToUpdate . step Calls . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . is Call Of ( old Step )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Step Def Ġ= Ġupdate Step Def Of Step Call ( updated Step Def , Ġindex , Ġnew Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Comp osed Step Without Re initial izing Caches ( updated Step Def , Ġrecursive Save Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġfind Steps That Call ( step : ĠComp osed Step Def ): ĠList < Comp osed Step Def > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult : ĠMutable Set < Comp osed Step Def > Ġ= Ġmutable Set Of () ĊĊĠĠĠĠĠĠĠ Ġval Ġcomposed Steps Ġ= Ġsteps Cache (). get Comp osed Steps () ĊĠĠĠĠĠĠĠ Ġfor Ġ( composed Step Ġin Ġcomposed Steps ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( step Call Ġin Ġcomposed Step . step Calls ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( step Call . is Call Of ( step )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( composed Step ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġresult . toList () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Step Def Of Step Call ( step Def ToUpdate : ĠComp osed Step Def , Ġstep Call Index ToUpdate : ĠInt , Ġnew Step : ĠComp osed Step Def ): ĠComp osed Step Def Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdate Step Calls : ĠMutable List < Step Call > Ġ= Ġstep Def ToUpdate . step Calls . to Mutable List () ĊĊĠĠĠĠĠĠĠ Ġupdate Step Calls [ step Call Index ToUpdate ] Ġ= Ġupdate Step Calls [ step Call Index ToUpdate ]. copy ( step Def Ġ= Ġnew Step ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġstep Def ToUpdate . copy ( step Calls Ġ= Ġupdate Step Calls ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Comp osed Step Save ( composed Step : ĠComp osed Step Def ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvalidate Parameters ( composed Step ) ĊĠĠĠĠĠĠĠ Ġvalidate Comp osed Step Save Unique Pattern ( composed Step ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Parameters ( composed Step : ĠComp osed Step Def ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġparameters Ġ= Ġcomposed Step . step Pattern . getParam Step Pattern () ĊĊĠĠĠĠĠĠĠ Ġfor Ġ(( i , Ġpart ) Ġin Ġparameters . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalidate Comp osed Step ParamName ( part . name , Ġi , Ġcomposed Step ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Comp osed Step ParamName ( param Name : ĠString , Ġparam Index : ĠInt , Ġcomposed Step : ĠComp osed Step Def ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! File Step Def Signature Parser Factory . isValid ParameterName ( param Name )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠValidation Exception ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" invalid Ġstep Ġparameter Ġname Ġ[$ param Name ]" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ": Ġerror Ġfound Ġat Ġparameter Ġnumber Ġ${ param Index Ġ+ Ġ 1 } Ġof Ġcomposed Ġstep Ġ$ composed Step " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Comp osed Step Save Unique Pattern ( composed Step : ĠComp osed Step Def ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġold Path Ġ= Ġcomposed Step . old Path ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn Ġ// Ġcreate ĊĊĠĠĠĠĠĠĠ Ġval Ġold Step Ġ= Ġsteps Cache (). get Step At Path ( old Path ) Ġas ? ĠComp osed Step Def ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn Ġ// Ġupdate , Ġbut Ġthe Ġold Ġstep Ġwas Ġdeleted Ġin Ġthe Ġmean Ġtime ; Ġhandle Ġit Ġas Ġcreate ĊĊĠĠĠĠĠĠĠ Ġval Ġold Step Pattern Ġ= Ġold Step . step Pattern ĊĠĠĠĠĠĠĠ Ġval Ġnew Step Pattern Ġ= Ġcomposed Step . step Pattern ĊĊĠĠĠĠĠĠĠ Ġif Ġ( old Step Pattern Ġ== Ġnew Step Pattern ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġall Steps Ġ= Ġsteps Cache (). getAll Steps () ĊĠĠĠĠĠĠĠ Ġif Ġ( is Other Step With The Same Step Pattern As The New ( old Step Pattern , Ġnew Step Pattern , Ġall Steps )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠValidation Exception ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" another Ġstep Ġwith Ġthe Ġsame Ġpattern Ġexists Ġat Ġpath Ġ[ ${ old Step . path }] " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Step Calls Re cursively ( step Calls : ĠList < Step Call >) Ġ{ ĊĠĠĠĠĠĠĠ Ġfor Ġ( step Call Ġin Ġstep Calls ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcomposed Step Def Ġ= Ġstep Call . step Def Ġas ? ĠComp osed Step Def ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġcontinue ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Comp osed Step ( composed Step Def ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave External Resources ( composed Step : ĠComp osed Step Def ): ĠComp osed Step Def Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstep Calls : ĠList < Step Call > Ġ= Ġcomposed Step . step Calls . map Ġ{ Ġstep Call Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave External Resources ( step Call ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcomposed Step . copy ( step Calls Ġ= Ġstep Calls ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Test External Resources ( test Model : ĠTest Model ): ĠTest Model Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstep Calls : ĠList < Step Call > Ġ= Ġtest Model . step Calls . map Ġ{ Ġstep Call Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave External Resources ( step Call ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġafter Hooks : ĠList < Step Call > Ġ= Ġtest Model . after Hooks . map Ġ{ Ġstep Call Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave External Resources ( step Call ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtest Model . copy ( step Calls Ġ= Ġstep Calls , Ġafter Hooks Ġ= Ġafter Hooks ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Feature External Resources ( feature : ĠFeature ): ĠFeature Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbefore All : ĠList < Step Call > Ġ= Ġfeature . hooks . before All . map Ġ{ Ġstep Call Ġ-> Ġsave External Resources ( step Call )} ĊĠĠĠĠĠĠĠ Ġval ĠbeforeEach : ĠList < Step Call > Ġ= Ġfeature . hooks . before Each . map Ġ{ Ġstep Call Ġ-> Ġsave External Resources ( step Call )} ĊĠĠĠĠĠĠĠ Ġval ĠafterEach : ĠList < Step Call > Ġ= Ġfeature . hooks . after Each . map Ġ{ Ġstep Call Ġ-> Ġsave External Resources ( step Call )} ĊĠĠĠĠĠĠĠ Ġval Ġafter All : ĠList < Step Call > Ġ= Ġfeature . hooks . after All . map Ġ{ Ġstep Call Ġ-> Ġsave External Resources ( step Call )} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġfeature . copy ( hooks Ġ= Ġfeature . hooks . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbefore All Ġ= Ġbefore All , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbeforeEach Ġ= ĠbeforeEach , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠafterEach Ġ= ĠafterEach , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġafter All Ġ= Ġafter All ĊĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave External Resources ( step Call : ĠStep Call ): ĠStep Call Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġargs With New Names : ĠList < Arg > Ġ= Ġstep Call . args . map Ġ{ Ġarg Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave External Resource ( arg ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġstep Call . copy ( args Ġ= Ġargs With New Names ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġif ĠArg Ġdoes Ġnot Ġrepresent Ġan Ġexternal Ġresource , Ġdo Ġnothing ; ĊĠĠĠĠ Ġ* Ġotherwise Ġsave Ġit Ġand Ġreturn Ġthe Ġnew Ġname ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġsave External Resource ( arg : ĠArg ): ĠArg Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġtodo : Ġdon 't Ġsave Ġif Ġthe Ġcontent Ġdidn 't Ġchange ? ĊĠĠĠĠĠĠĠ Ġval Ġpath : Ġcom . tester um . model . infrastructure . path . Path Ġ= Ġarg . path ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġreturn Ġarg Ġ// Ġif Ġwe Ġdon 't Ġhave Ġa Ġpath , Ġthen Ġthis Ġis Ġan Ġinternal Ġresource ĊĊĠĠĠĠĠĠĠ Ġval Ġresource Context : ĠResource Context Ġ= Ġresource File Service . save ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresource Context Ġ= ĠResource Context ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġold Path Ġ= Ġarg . old Path , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Ġ= Ġpath , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbody Ġ= Ġarg . content . or Empty () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresources Dir Ġ= Ġget Resources Dir () ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġval Ġactual Path : Ġcom . tester um . model . infrastructure . path . Path Ġ= Ġresource Context . path ĊĊĠĠĠĠĠĠĠ Ġreturn Ġarg . copy ( path Ġ= Ġactual Path ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġre initialize Caches () Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġre - loading Ġsteps Ġ& Ġtests Ġto Ġmake Ġsure Ġtests Ġare Ġresolved Ġproperly ĊĠĠĠĠĠĠĠ Ġ// Ġto Ġoptimize , Ġwe Ġcould Ġre - load Ġonly Ġthe Ġaffected Ġtests Ġand / or Ġsteps ĊĠĠĠĠĠĠĠ Ġweb Project Manager . getProject Services (). re initialize Steps Cache () ĊĠĠĠĠĠĠĠ Ġweb Project Manager . getProject Services (). re initialize Tests Cache () ĊĠĠĠĠĠĠĠ Ġweb Project Manager . getProject Services (). re initialize Feature Cache () ĊĠĠĠ Ġ} Ċ Ċ } Ċ