diff --git a/IDE test results.html b/IDE test results.html new file mode 100644 index 0000000..d24f494 --- /dev/null +++ b/IDE test results.html @@ -0,0 +1,6715 @@ + + + + + + + + + + + + +
Test Suite: _SelBlocks-TestSuite.html
Test cases: 58 total / 57 passed / 1 failed
Commands: 989 total / 904 passed / 1 failed / 84 skipped

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Index of test cases
README
eval
branching
if-1
if-2
if-3
try - noop
try - finally with no error
try - catch but no error
try - catch specific error
try - catch specific error then finally
try - catch throw finally throw
try - bubble up to catch ALL
try - bubble up to catch ALL via finally
try - bubble up out of noop try to catch specific error
try - bubble up to catch specific error
try - bubble up to catch specific error via finally
try - throw catch rethrow
try - bubble out of nested function calls
try - command bubbling break with finally
try - command bubbling intra try break
try - command bubbling continue with finally
try - command bubbling intra try continue
try - command bubbling error replaced by return
try - command bubbling error replaced by return 2
try - command bubbling return replaced by error
try - exitTest with finally processing
try - try without matching catch
while
for
foreach
foreach-xpath
forjson
forxml
continue-break 1
continue-break 2
continue-break 3
continue-break 4
nested-loops
function
function-recursive
issue-2-function
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
GlobalFunctions
CallGlobalFunction
DefineFunctionParameters - Base
DefineFunctionParameters - With Default Values
StoreLocal - Function Scope
StoreGlobal - Function Scope
StoreGlobal - While Scope
StoreLocal - While Scope
Store - Behaves as StoreLocal
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
+ +


+ + + + + + + + + +
Test case: README
-- SelBench is required for this testsuite
openhttp://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.html
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: eval
resetEmitted
--- isOneOf()
emit"dilbert".isOneOf("dilbert","dogbert","mordac")
emit"bob".isOneOf("dilbert","dogbert","mordac")
--- mapTo()
emit"red".mapTo("primary", ["red","green","blue"])
emit"orange".mapTo("primary", ["red","green","blue"])
--- translate()
emit"red".translate("e", "E")
emit"red".translate(["red", "green", "blue"], ["blue", "red", "green"])
--- check results
assertEmitted"true~false~primary~orange~rEd~blue"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: branching
resetEmitted
emit"BEFORE"
gotoHERE
emit"A"
labelHERE
gotoIftrueTHERE
emit"B"
labelTHERE
skipNext
emit"C"
emit"AFTER"
assertEmitted"BEFORE~AFTER"
=== Error validations
-!-
expectError"Target label 'NOWHERE' is not found"
gotoNOWHERE
-!-
expectError"Target label 'NOWHERE' is not found"
gotoIftrueNOWHERE
-!-
expectError"Requires a number > 1"
skipNext-1
-!-
expectError/.*random.* (is not |is un)defined/
skipNextrandom
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: if-1
resetEmitted
emit"BEFORE"
--
iftrue
emit"truthy"
endIf
--
iffalse
emit"falsey"
endIf
--
iftrue
emit"A"
else
emit"B"
endIf
--
iffalse
emit"X"
else
emit"Y"
endIf
--
iffalse
emit"false teeth"
else
iftrue
emit"truthF"
else
emit"false false"
endIf
endIf
--
if"dilbert".isOneOf("dogbert","dilbert","wally")
emit"office mate"
endIf
if"dilbert".isOneOf("ratbert","alice","asok")
emit"mate"
else
emit"coffee mate"
endIf
if"mordac".isOneOf("bob the dinosaur","garbage man","mordac")
emit"cell mate"
else
emit"don't wait"
endIf
emit"AFTER"
--- check results
assertEmitted"BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: if-2
resetEmitted
==
iftrue
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
--
iffalse
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
--
iffalse
emit"if-y"
elseIftrue
emit"elseIf-a1y"
elseIftrue
emit"else-a2y"
endIf
--
iffalse
emit"if-y"
elseIffalse
emit"elseIf-b1y"
elseIftrue
emit"elseIf-b2y"
endIf
--
iffalse
emit"if-y"
elseIffalse
emit"elseIf-y"
else
emit"else-y"
endIf
assertEmitted"if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: if-3
resetEmitted
--
foreachi2, 0, 1, 4, 3, 5
ifi == 0
emit"if-${i}"
elseIfi == 1
emit"elseIf-${i}"
elseIfi == 2
emit"elseIf-${i}"
elseIfi == 3
emit"elseIf-${i}"
else
emit"else-${i}"
endIf
endForeach
assertEmitted"elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - noop
log"-- no-op try --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
tryt-noop
emit"trying"
endTryt-noop
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - finally with no error
log"-- try/finally, w/no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
tryt-fin
emit"trying"
finally
emit"finally"
endTry
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~finally~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - catch but no error
log"-- try/catch, but no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trytc0
emit"trying"
catch
assertEval"should NEVER enter this catch block due to no error"
endTry
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - catch specific error
log"-- catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trytc1
throw"blamo catch ALL"
assertEval"this command should not be reached, due to thrown"
catch
emit"caught '" + _error.message + "'"
endTry
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~caught 'blamo catch ALL'~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - catch specific error then finally
log"-- catch specific error, then finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
tryt-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel-1
emit"([/"
v v v
tryt-spec-inner
emit"trying inner"
throw"blamo inner"
assertEval"this command should not be reached, due to throw"
catch/blamo inner/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-spec-inner
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
endTryt-spec-outer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - catch throw finally throw
log"-- catch/throw, finally/throw --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trytcf-trap
v v v
assertEvalselblocks.tcf.nestingLevel0
trytcf
emit"trying"
emit"throwing A"
throw"blamoA"
assertEval"this command should not be reached, due to thrown"
catch/blamoA/
emit"caught '" + _error.message + "'"
emit"throwing B"
throw"blamoB"
finally
emit"finally"
emit"throwing C"
throw"blamoC"
endTry
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught '" + _error.message + "'"
endTry
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - bubble up to catch ALL
log"-- bubble up to catch ALL --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
tryt-all-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
v v v
tryt-all-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
endTryt-all-inner
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-all-outer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - bubble up to catch ALL via finally
log"-- bubble up to catch ALL via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
tryt-allfin-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
v v v
tryt-allfin-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-allfin-inner
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-allfin-outer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - bubble up out of noop try to catch specific error
log"-- bubble out of no-op try to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trynoop-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
v v v
tryop-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
endTryop-inner
^ ^ ^ ^
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrynoop-outer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - bubble up to catch specific error
log"-- bubble up to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
v v v
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
^ ^ ^ ^
catch/blamo/
emit"caught '" + _error.message + "'"
endTrybub-spec-outer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - bubble up to catch specific error via finally
log"-- bubble up to catch specific error via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
v v v
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
^ ^ ^ ^
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-spec-outer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - throw catch rethrow
log"-- throw, catch, rethrow --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
tryouter
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
v v v
tryinner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing blamo1"
throw"blamo1"
assertEval"this command should not be reached, due to throw"
catch/blamo1/
emit"caught '" + _error.message + "'"
emit"throwing blamo2"
throw"blamo2"
endTryinner
^ ^ ^ ^
catch/blamo2/
emit"caught '" + _error.message + "'"
endTryouter
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - bubble out of nested function calls
log"-- bubble out of nested function calls --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trybub-invoke
emit"trying"
emit"calling"
callsubBubn = 0
assertEval"this command should not be reached, due error thrown in function"
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-invoke
assertEvalselblocks.tcf.nestingLevel-1
^ ^ ^ ^
functionsubBubn
v v v
trytcf-inner
emit"${n}) trying-inner"
ifn < 2
emit"${n}) calling"
callsubBubn = n+1
else
emit"${n}) throwing"
throw"blamo"
endIf
finally
emit"${n}) finally"
endTrytcf-inner
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel0
endFunction
emit"/])"
assertEmitted"([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - command bubbling break with finally
log"-- command bubbling, break w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
v v v
trybreaker
emit"${w}) trying"
ifw==2
emit"${w}) BREAK"
break
endIf
finally
emit"${w}) finallying"
endTrybreaker
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - command bubbling intra try break
log"-- command bubbling, intra-try break --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trybreaker
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) BREAK"
break
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrybreaker
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) BREAK~finallying~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - command bubbling continue with finally
log"-- command bubbling, continue w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
v v v
trycontinuer
emit"${w}) trying"
ifw==2
emit"${w}) CONTINUE"
continue
endIf
finally
emit"${w}) finallying"
endTrycontinuer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - command bubbling intra try continue
log"-- command bubbling, intra-try continue --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trycontinuer
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) CONTINUE"
continue
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrycontinuer
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - command bubbling error replaced by return
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubA
emit"returned ${_result}"
functioncmdBubA
emit"in cmdBubA"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"returning (2)"
return2
endTry
^ ^ ^ ^
assertEval"this command should not be reached, due to return/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - command bubbling error replaced by return 2
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubB
emit"returned ${_result}"
functioncmdBubB
emit"in cmdBubB"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trycmdBub-tcf
emit"trying"
emit"throwing"
throw"short-lived error"
finally
emit"finallying"
emit"returning (2)"
return2
endTry
^ ^ ^ ^
assertEval"this command should not be reached, due to throw/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - command bubbling return replaced by error
log"-- command bubbling, return replaced by error --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubC
emit"returned ${_result}"
functioncmdBubC
emit"in cmdBubC"
assertEvalselblocks.tcf.nestingLevel-1
v v v
trycmdBub-tcf-guardrail
assertEvalselblocks.tcf.nestingLevel0
v v v
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"throwing"
throw"this-error-replaces-return-1"
endTry
^ ^ ^ ^
catch/this-error-replaces-return-1/
emit"caught '" + _error.message + "'"
assertEvalselblocks.tcf.nestingLevel0
endTry
^ ^ ^ ^
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - exitTest with finally processing
log"-- exitTest w/finally processing --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
v v v
tryabort
emit"trying"
emit"exitTest ..."
exitTest
finally
emit"finallying"
assertEmitted"([/~trying~exitTest ...~finallying"
resetEmitted
endTryabort
^ ^ ^ ^
assertEval"this command should not be reached, due to exitTest above"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: try - try without matching catch
log"-- try without matching catch --"
resetEmitted
assertEvalselblocks.tcf.nestingLevel-1
v v v
trymiss
assertEvaltruetrue
throw"blamo will NOT be caught at all"
assertEval"this command should not be reached"
catch/will NOT catch it/
log"caught miss '" + _error.message + "'"
finally
log"finally"
endTrymissCommand execution failure. Please search the user group at https://groups.google.com/forum/#!forum/selenium-users for error details from the log window. The error message is: blamo will NOT be caught at all
^ ^ ^ ^
assertEvalselblocks.tcf.nestingLevel-1
emit"trying"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: while
resetEmitted
deleteVarsw
store3w
emit"START: ${w}"
--- no iterations
whilew == 42
emit"SHOULD NEVER HAPPEN"
endWhile
--- several iterations
whilew > 0
emit"iter=${w}"
storeEval${w}-1w
endWhile
emit"END: ${w}"
--- check results
assertEmitted"START: 3~iter=3~iter=2~iter=1~END: 3"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: for
resetEmitted
deleteVarsf
emit"START ${f}"
fors=0,f=3; f <= 5; f++
emit"iter=${f}.${s}"
endFor
emit"END ${f}"
--- check results
assertEmitted"START ${commands}quot; + "{f}~iter=3.0~iter=4.0~iter=5.0~END ${commands}quot; + "{f}"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: foreach
resetEmitted
deleteVars_i, fe
emit"START ${_i}-${fe}"
foreachfe"dilbert", "dogbert", "wally"
emit"${_i}) ${fe}"
endForeach
emit"END ${_i}-${fe}"
--- check results
assertEmitted"START ${commands}quot; + "{_i}-${commands}quot; + "{fe}~0) dilbert~1) dogbert~2) wally~END ${commands}quot; + "{_i}-${commands}quot; + "{fe}"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: foreach-xpath
resetEmitted
echo$x("//input")
echo$X("//input")
echobegin
emit"START ${_i}) ${link}"
foreachlink$X("//input")
emit"${_i}) ${link}"
echo${link}
endForeach
emit"END ${_i}) ${link}"
assertEmitted"START ${" + "_i}) ${" + "link}~0) [object HTMLInputElement]~1) [object HTMLInputElement]~2) [object HTMLInputElement]~END ${" + "_i}) ${" + "link}"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: forjson
ifglobalContext.onServer === true
store../data/forjson.jsonforJsonFileName
else
storedata/forjson.jsonforJsonFileName
endIf
resetEmitted
deleteVarsjname
emit"START ${jname}"
--- forJson
forJson${forJsonFileName}
emitjname
endForJson
emit"INTERMISSION ${jname}"
--- load a varset
loadJsonVars${forJsonFileName}jname == "dogbert"
emit"END ${jname}"
--- check results
assertEmitted"START ${commands}quot; + "{jname}~dilbert~dogbert~wally~INTERMISSION ${commands}quot; + "{jname}~END dogbert"
=== Error validations
-!-
expectError"Requires a JSON file path or URL"
loadJsonVars
-!-
expectError"Multiple JSON objects are not valid for this command"
loadJsonVars${forJsonFileName}
-!-
expectError'"flubber" is not a boolean expression'
loadJsonVars${forJsonFileName}"flubber"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: forxml
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
resetEmitted
deleteVarsxname
emit"START ${xname}"
--- forXml
forXml${forXmlFileName}
emitxname
endForXml
emit"INTERMISSION ${xname}"
--- load a varset
loadXmlVars${forXmlFileName}xname == "dogbert"
emit"END ${xname}"
--- check results
assertEmitted"START ${commands}quot; + "{xname}~dilbert~dogbert~wally~INTERMISSION ${commands}quot; + "{xname}~END dogbert"
loadXmlVars${forXmlFileName}xname == "dogbert"
=== Error validations
-!-
expectError"Requires an XML file path or URL"
loadXmlVars
-!-
expectError"Multiple XML elements are not valid for this command"
loadXmlVars${forXmlFileName}
-!-
expectError'"flubber" is not a boolean expression'
loadXmlVars${forXmlFileName}"flubber"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: continue-break 1
resetEmitted
deleteVarsf
forf=3; f <= 9; f++
continuef == 6
iff > 6
iff == 7
continue
else
break
endIf
endIf
emit"iter=${f}"
endFor
--- check results
assertEmitted"iter=3~iter=4~iter=5"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: continue-break 2
resetEmitted
store0i
whilei++ < 10
continuei==3
breaki==5
emit"iter=${i}"
endWhile
--- check results
assertEmitted"iter=1~iter=2~iter=4"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: continue-break 3
resetEmitted
foreachfe"dilbert","dogbert","wally"
continuefe=="dogbert"
breakfe=="wally"
emit"iter=${fe}"
endForeach
--- check results
assertEmitted"iter=dilbert"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: continue-break 4
resetEmitted
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
forXml${forXmlFileName}
continuexname=="dogbert"
breakxname=="wally"
emit"iter=${xname}"
endForXml
--- check results
assertEmitted"iter=dilbert"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: nested-loops
resetEmitted
deleteVarsi, n, uname
startTimer
store2i
emit"START ${i}"
whilei > 0
emit"while=${i}"
foreachuname"dilbert", "dogbert"
emit"foreach=${uname}"
forn = 2; n <=3; n++
emit"FOR=${n}"
forn = 7; n <= 8; n++
emit"for=${n}"
endFor
endFor
emit"endFor ${n}"
endForeach
storeEval${i}-1i
endWhile
emit"END ${i}"
timerElapsed
--- check results
assertEmitted"START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: function
deleteVarssname, srole
assertEval"START ${sname} ${srole}" === "START ${commands}quot; + "{sname} ${commands}quot; + "{srole}"true
--- first line
calldoSomethingsname = "dilbert,Q", srole = "goof"
assertEval"${_result}" === "sname=dilbert,Q,srole=goof"true
deleteVarssname, srole
===
functiondoSomethingsname
return"sname=${sname},srole=${srole}"
endFunctiondoSomething
===
deleteVarssname, srole
calldoSomethingsname = "dogbert", srole = "woof"
assertEval"${_result}" === "sname=dogbert,srole=woof"true
deleteVarssname, srole
calldoSomethingsname = "ratbert", srole = "squeak"
assertEval"${_result}" === "sname=ratbert,srole=squeak"true
deleteVarssname, srole
---
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
assertEval"${_result}" === "sname=${sname},srole=super=user"true
deleteVarssname, srole
endForeach
assertEval"DONE ${sname} ${srole}" === "DONE ${commands}quot; + "{sname} ${commands}quot; + "{srole}"true
=== Error validations
-!-
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
=== deprecated script commands
deleteVarssname, srole
scriptdoDeprecatedsname
return"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEval"${_result}" === "sname=wally,srole=lazy"true
deleteVarssname, srole
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: function-recursive
resetEmitted
deleteVarsdegree, n, _result, ud
store7degree
startTimerfactorial ${degree}
callfacn=degree
timerElapsed
emitdegree + "!=" + _result
===
--- recursive factorial
functionfacn
ifn <= 1
return1
else
callfacn = n-1
emit_result
returnn * _result
endIf
endFunction
===
--- mutual recursive
functionuno
emit"UNO"
storeEval${ud}-1ud
ifud > 0
calldue
endIf
endFunctionuno
---
functiondue
emit"DUE"
storeEval${ud}-1ud
ifud > 0
calluno
endIf
endFunctiondue
---
store5ud
calluno
===
assertEmitted"1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + +
Test case: issue-2-function
functionxyz
log'here'
endFunction
callxyz
+ +


+ + + + + + + + + + + + + + + + + + +
Test case: exitTest - base case
resetEmitted
exitTest
throw"shouldn't happen"
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: exitTest - from within a loop
-- from within a loop
fori=0; i < 5; i++
ifi == 3
exitTest
endIf
ifi === 3
throw"This test should exit when the increment gets to 3, and this should never be thrown."
endIf
endFor
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: exitTest - from within a function
-- from within a function
calldoSubExit
throw"shouldn't happen"
functiondoSubExit
exitTest
endFunctiondoSubExit
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + +
Test case: GlobalFunctions
getEvalglobalStoredVars = {};
functionsetGlobalVar
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: DefineFunctionParameters - Base
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionbobx,y
assertEval"${x}" === "overwritten"true
assertEvalstoredVars.y === undefinedtrue
endFunction
callbobx="overwritten"
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEvalstoredVars.y === undefinedfalse
assertEval"${y}" === "original";true
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: DefineFunctionParameters - With Default Values
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
check that x and y do not leak outside of function scope
functionleakTestx="fn default x",y="fn default y"
storeoverwrittenx
storeoverwritteny
endFunction
check that x and y both take default values when unspecified, but only in function scope
functiondefaultsTestx="fn default x",y="fn default y"
assertEval${x} === "fn default x"true
store"overwritten"x
assertEval${x} === "overwritten"true
assertEval${y} === "fn default y"true
store"overwritten"y
assertEval${y} === "overwritten"true
endFunction
defaultsTest 00
calldefaultsTest
leakTest 00
callleakTest
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
leakTest 01
callleakTesty = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
leakTest 10
callleakTestx = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
leakTest 11
callleakTestx = "overwritten", y = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: StoreLocal - Function Scope
setting a local variable from function scope
functionblockScopeVars
storeLocalthis is stored locallyl
local variables aren't put onto the global variable object
assertEvalstoredVarsGlobal.l === "this is stored locally"false
local variables will be accessible through stored vars,
block vars, and ${} notation as long as they're in scope.
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
local variables must not persist after exiting scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: StoreGlobal - Function Scope
setting a global variable from function scope
functionblockScopeVars
storeGlobalthis is stored globallyg
global variables should exist everywhere
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endFunction
global variables must persist after exiting scope
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: StoreGlobal - While Scope
clearing any values from previous tests
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
store1i
setting a global variable from while scope
whilei > 0
store0i
storeGlobalthis is stored globallyg
global variables should exist everywhere
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endWhile
global variables must persist after exiting scope
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: StoreLocal - While Scope
clearing any values from previous tests
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
store1i
setting a local variable from while scope
whilei > 0
store0i
storeLocalthis is stored locallyl
local variables aren't put onto the global variable object
assertEvalstoredVarsGlobal.l === "this is stored locally"false
local variables will be accessible through stored vars,
block vars, and ${} notation as long as they're in scope.
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endWhile
local variables must not persist after exiting scope
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: Store - Behaves as StoreLocal
setting a local variable from function scope
functionblockScopeVars
storethis is stored locallyl
local variables aren't put onto the global variable object
assertEvalstoredVarsGlobal.l === "this is stored locally"false
local variables will be accessible through stored vars,
block vars, and ${} notation as long as they're in scope.
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
local variables must not persist after exiting scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: Function - Can Return Value
functionreturnsValue
return"banana"
endFunction
callreturnsValue
assertEval"${_result}" === "banana"true
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: StoreAt - Function Scope Nesting
function for setting a variable at it's location / ancestor / parent
functionstorel
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
storeAt only makes global vars if it can't find a definition in preceeding scopes
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
storeAt makes the variables available in parent scopes so
they're visible as if they were local.
block vars, and ${} notation work transparently.
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
endFunction
storeAt will set the value of a named variable in a parent scope
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
callstorel
when defined in a parent scope, the variable will not bubble up to global scope
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
when defined in a parent scope, the nearest ancestor catches the new value for the variable
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: StoreAt - While Scope Nesting
storeAt will set the value of a named variable in a parent scope
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
while block setting a variable at it's location / ancestor / parent
storeLocal3x
whilex !== 0
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
storeAt only makes global vars if it can't find a definition in preceeding scopes
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
storeAt makes the variables available in parent scopes so
they're visible as if they were local.
block vars, and ${} notation work transparently.
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
storeEvalLocalx -= 1
endWhile
deleteVarx
when defined in a parent scope, the variable will not bubble up to global scope
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
when defined in a parent scope, the nearest ancestor catches the new value for the variable
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ +


+ + + + + + + + + + + + + + + + + + +
Test case: sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ + diff --git a/README.md b/README.md index 01c9f66..fe08373 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,60 @@ -SelBlocks 2 -========= +# SelBlocks 2 +![SelBlocks Logo](https://raw.githubusercontent.com/refactoror/SelBlocks/master/sel-blocks-fx_xpi/chrome/skin/selblocksLogo.png) -SelBlocks is a language extension for Selenium IDE +SelBlocks is a language extension for Selenese that works on both the Selenium IDE and Selenium standalone server. It allows intelligent, data driven, tests to be recorded and composed in Selenium IDE, then run on any browser supported by Selenium server. With SelBlocks there is no need to translate the tests into another language at all! Experience web application testing and automation that's so easy a child could do it. Seriously, we've taught kids how to use this. -It provides Selenium commands for javascript-like conditionals, looping, callable functions, error catching, and JSON/XML driven parameterization. +> My eight year old nephew's eyes got huge when he said *"You mean I can click __all__ the buttons?"* and I told him yes. Then showed him how to do it. +> -- Kastor -Features +## Features +* Variables can be configured via external XML and/or JSON files. +* Functions are namespaced. They can be defined in test libraries, then called from any test case in the suite with `testCaseTitle.functionName`. +* Command parameters are javascript expressions that are evaluated with Selenium variables in scope, which can therefore be referenced by their simple names, e.g.: i+1 +* A function definition can appear anywhere, (they are skipped over in normal execution flow). +* Functions can be called recursively. +* Function and loop parameters use regular Selenium variables that are local to the block, overriding variables of the same name, and that are restored when the block exits. * Adds the following control structures to Selenese: * if, elseIf, else * try, catch, finally, throw * for, foreach, while, continue, break * call, function, return - * loadJsonVars, loadXmlVars, forJson, forXml + * goto, gotoIf, label, skipNext + * forJson, forXml * exitTest -* Function and loop parameters use regular Selenium variables that are local to the block, overriding variables of the same name, and that are restored when the block exits. -* Command parameters are javascript expressions that are evaluated with Selenium variables in scope, which can therefore be referenced by their simple names, e.g.: i+1 -* Variables can be configured via external XML and/or JSON files. -* A function definition can appear anywhere, (they are skipped over in normal execution flow). -* Functions can be called recursively. +* Adds the following variable declarators to Selenese: + * *Scoped `store` command* + * storeLocal : stores variables in the current block scope, the builtin `store` command now creates local variables as well. + * storeGlobal : stores variables in global scope + * storeAt : stores variable values in the parent scope where they were defined, or creates a global variable if no parent scope defined it. + * loadJsonVars : creates variables in the current block scope, as defined by the given JSON file or URL. + * loadXmlVars : creates variables in the current block scope, as defined by the given XML file or URL. + * *Scoped storeEval* : built in Selenese command, storeEval stores the result of evaluating the given javascript. + * SelBlocks adds : storeEvalLocal, storeEvalGlobal, and storeEvalAt + * *Scoped storeText* : stores the text of the located element. + * SelBlocks adds : storeLocalText, storeGlobalText, and storeAtText + * *Scoped storeAttribute* : stores the value of the located attribute. + * SelBlocks adds : storeLocalAttribute, storeGlobalAttribute, and storeAtAttribute + +## Installation + +The [Firefox installer](https://addons.mozilla.org/en-US/firefox/addon/selenium-ide-sel-blocks/) is the latest published release. It is available from the firefox addons site, or just search for it in your addons menu. + +To install the latest development version, clone this repository and put a file in your firefox extensions directory called `sel-blocks@chris.noe`. In that file just paste the full path to the `sel-blocks-fx_xpi` directory. Now, you'll be able to get the cutting edge latest stuff by pulling it in whenever you want. As an added bonus, when you switch branches the extension will load with that branch's code. + +The Selenium server extension file is at "/user extension/user-extensions.js". Grab a copy and follow the directions in the SeleniumHTMLRunner.cmd file. + +## Documentation + +Find the docs at http://refactoror.wikia.com/wiki/Selblocks_Reference + +## Author + +* [Chris Noe](https://github.com/refactoror) -[Firefox Installer](https://addons.mozilla.org/en-US/firefox/addon/selenium-ide-sel-blocks/) / [Documentation](http://refactoror.wikia.com/wiki/Selblocks_Reference) +## Contributors -Contributors +* [Matthew Kastor](https://github.com/matthewkastor) If you would like to contribute code to SelBlocks, you can do so by forking this project, and then submitting a pull request. Contributed code must be able to pass the full test suite, and should include additional tests to prove the correctness of the new or modified code. diff --git a/build/createSelblocksUserExtensions.cmd b/build/createSelblocksUserExtensions.cmd new file mode 100644 index 0000000..c264e96 --- /dev/null +++ b/build/createSelblocksUserExtensions.cmd @@ -0,0 +1,10 @@ +@echo off +SETLOCAL +SET extensionsDir=%~dp0..\sel-blocks-fx_xpi\chrome\content\extensions +SET userExtensionDir=%~dp0..\user extension + +SET copylist="%userExtensionDir%\scripts\config.js"+"%extensionsDir%\name-space.js"+"%extensionsDir%\logger.js"+"%extensionsDir%\function-intercepting.js"+"%extensionsDir%\xpath-processing.js"+"%extensionsDir%\expression-parser.js"+"%extensionsDir%\selenium-executionloop-handleAsExitTest.js"+"%extensionsDir%\selenium-executionloop-handleAsTryBlock.js"+"%extensionsDir%\selblocks.js" + +copy %copylist% /B "%userExtensionDir%\user-extensions.js" /B +ENDLOCAL +EXIT /B %ERRORLEVEL% \ No newline at end of file diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/name-space.js b/sel-blocks-fx_xpi/chrome/content/extensions/name-space.js index 062968e..eae3ae8 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/name-space.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/name-space.js @@ -1,6 +1,11 @@ // SelBlocks name-space var selblocks = { name: "SelBlocks" }; +// I don't want to redeclare the variable when the user-extension is generated +// I don't want the scripts to blow up when the firefox extension is used. +// This is an alias on the global scope that references the global scope. +globalContext = this; + (function($$){ /* Starting with FF4 lots of objects are in an XPCNativeWrapper, diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index f6ba739..d57ec40 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -44,7 +44,6 @@ * script can be monitored using the Stored Variables Viewer addon. */ - // =============== global functions as script helpers =============== // getEval script helpers @@ -82,7 +81,6 @@ function $X(xpath, contextNode, resultType) { // selbocks name-space (function($$){ - // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: // Global functions are intentional features provided for use by end user's in their Selenium scripts. @@ -157,16 +155,139 @@ function $X(xpath, contextNode, resultType) { return null; }; - //=============== Call/Scope Stack handling =============== var symbols = {}; // command indexes stored by name: function names var blockDefs = null; // static command definitions stored by command index var callStack = null; // command execution stack + var contextManager; // makes block scoped variables work + // intentionally global var + storedVarsGlobal = storedVars; + /** + * Manages variable scope for functions, blocks, etc. + * @class ContextManager + */ + function ContextManager() { + // intentionally global var + storedVarsLocal = Object.create(storedVarsGlobal); + storedVars = storedVarsLocal; + this.contexts = []; + this.enter(); + } + /** + * Enters a new variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.enter = function enterContext() { + var _o = storedVars; + var context = { + here : Object.create(storedVars), + back : _o + }; + this.contexts.push(context); + storedVars = context.here; + storedVarsLocal = context.here; + }; + /** + * Exits to the previous variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.exit = function exitContext() { + if (this.contexts.length > 0) { + var context = this.contexts.pop(); + storedVars = context.back; + storedVarsLocal = context.back; + } else { + throw new Error("No context to exit from"); + } + }; + /** + * Resets to the top variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.reset = function exitContext() { + storedVars = storedVarsGlobal; + build_sendkeys_maps(); + storedVarsLocal = storedVarsGlobal; + this.contexts = []; + this.enter(); + }; + /** + * Stores variable into the context chain in the last parent where it was + * defined. This allows values to bubble up to their relevant parent so that + * you don't have to pass everything in global scope. The variable must exist + * in a parent scope in order to be caught there, otherwise it will get to + * the global scope and be set there. + * @param {String} propName The name of the variable. + * @param {Mixed} val Any value you could set for a variable. + */ + ContextManager.prototype.storeAtClosestContextWithPropName = + function storeAtClosestContextWithPropName (propName, val) { + var out = undefined; + var idx = this.contexts.length - 1; + while (idx >= 0 && out === undefined) { + if(this.contexts[idx].here.hasOwnProperty(propName)) { + this.contexts[idx].here[String(propName)] = val; + out = true; + } + idx--; + } + if(out === undefined) { + storedVarsGlobal[String(propName)] = val; + $$.LOG.warn(String(propName) + " not found, setting global variable"); + } + }; + contextManager = new ContextManager(); + /** + * State information about the cache. + * currentCaseTitle is the current case displayed in the UI + * activeCaseTitle is the cashed case where commands are actually being pulled + * from. + * commandIndex is the current index of the commands array in the active case + * suites are the cached test suites commands, symbols, and blockDefs + */ + var cachedCommandsData = { + initializing : true, + currentCaseTitle : '', + activeCaseTitle : '', + commandIndex : 0, + suites : Object.create(null), + /** + * Caches information about the current test case + */ + cacheCommands : function cacheCacheCommands(symbols, commands, blockDefs) { + cachedCommandsData.initializing = false; + cachedCommandsData.suites[cachedCommandsData.currentCaseTitle] = { + 'symbols' : symbols, + 'commands' : commands, + 'blockDefs' : blockDefs + } + }, + /** + * Starts a new suite cache. + */ + init : function cacheInit() { + cachedCommandsData.initializing = true; + var _mytitle; + if(globalContext.onServer === true) { + _mytitle = testCase.htmlTestCase.testDocument.title || "untitiled"; + } else { + _mytitle = testCase.title || "untitiled"; + } + // the current case displayed in the IDE + cachedCommandsData.currentCaseTitle = String(_mytitle); + // the current case for looking up functions + cachedCommandsData.activeCaseTitle = String(_mytitle); + // the index used for executing commands, this is decoupled from the + // testCase.debugIndex because what's being executed doesn't always + // move the row cursor in the UI anymore. + cachedCommandsData.commandIndex = 0; + } + }; // the idx of the currently executing command function idxHere() { - return testCase.debugContext.debugIndex; + return cachedCommandsData.commandIndex; } // Command structure definitions, stored by command index @@ -184,7 +305,13 @@ function $X(xpath, contextNode, resultType) { // retrieve the blockDef at the given command idx function blkDefAt(idx) { - return blockDefs[idx]; + var where; + if(cachedCommandsData.initializing === true) { + where = blockDefs[idx]; + } else { + where = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].blockDefs[idx]; + } + return where; } // retrieve the blockDef for the currently executing command function blkDefHere() { @@ -242,33 +369,69 @@ function $X(xpath, contextNode, resultType) { if (!this.started) { this.started = true; this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; + cachedCommandsData.commandIndex = 0 + this.debugIndex; + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); } else { if (branchIdx !== null) { $$.LOG.info("branch => " + fmtCmdRef(branchIdx)); - this.debugIndex = branchIdx; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex = branchIdx; + } + cachedCommandsData.commandIndex = branchIdx; branchIdx = null; } else { - this.debugIndex++; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex++; + } + cachedCommandsData.commandIndex++; } } - // skip over comments - while (this.debugIndex < testCase.commands.length) { - var command = testCase.commands[this.debugIndex]; + + var command; + // skip over comments + while (cachedCommandsData.commandIndex < cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands.length) { + command = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands[cachedCommandsData.commandIndex]; + + if(globalContext.onServer === true) { + this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + command = this.currentRow.getCommand(); + command.type = "command"; + } + if (this.sejsElement) { + this.currentItem = agenda.pop(); + this.currentRowIndex = this.debugIndex; + } + } + if (command.type === "command") { + this.runTimeStamp = Date.now(); return command; } - this.debugIndex++; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex++; + } + cachedCommandsData.commandIndex++; + } + + if(globalContext.onServer === true) { + this.currentRow = null; + this.currentItem = null; } return null; } + /** + * Creates a pointer to the next command to execute. This pointer is used by + * nextCommand when considering what to do next. + * @param {Number} cmdIdx The index of the next command to execute. + */ function setNextCommand(cmdIdx) { - assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, - " Cannot branch to non-existent command @" + (cmdIdx+1)); + assert(cmdIdx >= 0 && cmdIdx < cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands.length, + " Cannot branch to non-existent command " + String(cachedCommandsData.activeCaseTitle) + " @" + (cmdIdx+1)); branchIdx = cmdIdx; } - // Selenium calls reset(): // * before each single (double-click) command execution // * before a testcase is run @@ -278,6 +441,7 @@ function $X(xpath, contextNode, resultType) { { $$.LOG.trace("In tail intercept :: Selenium.reset()"); try { + contextManager.reset(); compileSelBlocks(); } catch (err) { @@ -294,15 +458,21 @@ function $X(xpath, contextNode, resultType) { $$.fn.interceptReplace(testCase.debugContext, "nextCommand", nextCommand); }); - // get the blockStack for the currently active callStack + /** + * gets the blockStack for the currently active callStack + */ function activeBlockStack() { return callStack.top().blockStack; } // ================================================================================ - // Assemble block relationships and symbol locations + /** + * Assembles block relationships and symbol locations. + */ function compileSelBlocks() { + cachedCommandsData.init(); + symbols = {}; blockDefs = new BlockDefs(); var lexStack = new Stack(); var i; @@ -487,6 +657,7 @@ function $X(xpath, contextNode, resultType) { } throw new SyntaxError(cmdErrors.join("; ")); } + cachedCommandsData.cacheCommands(symbols, testCase.commands, blockDefs); //- command validation function assertNotAndWaitSuffix(cmdIdx) { assertCmd(cmdIdx, (testCase.commands[cmdIdx].command.indexOf("AndWait") === -1), @@ -504,7 +675,9 @@ function $X(xpath, contextNode, resultType) { // -------------------------------------------------------------------------------- - // prevent jumping in-to and/or out-of loop/function/try blocks + /** + * prevents jumping in-to and/or out-of loop/function/try blocks + */ function assertIntraBlockJumpRestriction(fromIdx, toIdx) { var fromRange = findBlockRange(fromIdx); var toRange = findBlockRange(toIdx); @@ -517,7 +690,9 @@ function $X(xpath, contextNode, resultType) { } } - // ascertain in which, if any, block that an locusIdx occurs + /** + * ascertain in which, if any, block that an locusIdx occurs + */ function findBlockRange(locusIdx) { var idx; for (idx = locusIdx-1; idx >= 0; idx--) { @@ -589,7 +764,7 @@ function $X(xpath, contextNode, resultType) { notifyFatal("Invalid character(s) in " + desc + " name: '" + name + "'"); } } - + Selenium.prototype.doLabel = function() { // noop }; @@ -719,9 +894,14 @@ function $X(xpath, contextNode, resultType) { tryState.execPhase = "trying"; if ($$.tcf.nestingLevel === 0) { - // enable special command handling - $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", + // enable special command handling + if(globalContext.onServer === true) { + $$.fn.interceptPush(htmlTestRunner.currentTest, "resume", $$.handleAsTryBlock, { manageError: handleCommandError }); + } else { + $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", + $$.handleAsTryBlock, { manageError: handleCommandError }); + } } $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); // continue into try-block @@ -874,10 +1054,14 @@ function $X(xpath, contextNode, resultType) { $$.LOG.warn("bubbleToTryBlock() called outside of any try nesting"); } var tryState = unwindToBlock(_hasCriteria); + var ret; while (!tryState && $$.tcf.nestingLevel > -1 && callStack.length > 1) { var callFrame = callStack.pop(); $$.LOG.info("function '" + callFrame.name + "' aborting due to error"); - restoreVarState(callFrame.savedVars); + if (storedVars._result) { ret = storedVars._result; } + contextManager.exit(); + storedVars._result = ret; + //restoreVarState(callFrame.savedVars); tryState = unwindToBlock(_hasCriteria); } return tryState; @@ -1189,6 +1373,7 @@ function $X(xpath, contextNode, resultType) { activeBlockStack().push(loopState); var localVars = _validateFunc(loopState); loopState.savedVars = getVarState(localVars); + contextManager.enter(); initVarState(localVars); // because with-scope can reference storedVars only once they exist _initFunc(loopState); } @@ -1210,8 +1395,13 @@ function $X(xpath, contextNode, resultType) { assertRunning(); assertActiveScope(blkDefHere().beginIdx); var loopState = activeBlockStack().top(); + var ret; if (loopState.isComplete) { - restoreVarState(loopState.savedVars); + if (storedVars._result) { ret = storedVars._result; } + contextManager.exit(); + storedVars._result = ret; + + //restoreVarState(loopState.savedVars); activeBlockStack().pop(); // done, fall out of loop } @@ -1261,38 +1451,59 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doCall = function(funcName, argSpec) { + var funcIdx, fName, caseName; assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? - if (argSpec) { + // throws an error if given gibberish. IE considers the assertion "var;" to be invalid. + // parseArgs, called further below, can handle the empty string just fine. + if (argSpec && argSpec != '') { assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); } - var funcIdx = symbols[funcName]; - assert(funcIdx!==undefined, " Function does not exist: " + funcName + "."); + if(funcName.match(/[.]/)) { + caseName = String(funcName.split(".")[0]); + fName = String(funcName.split(".")[1]); + } else { + caseName = String(cachedCommandsData.activeCaseTitle); + fName = String(funcName); + } + funcIdx = cachedCommandsData.suites[caseName].symbols[fName]; + assert(funcIdx!==undefined, " Function does not exist: " + funcName); + cachedCommandsData.activeCaseTitle = String(caseName); var activeCallFrame = callStack.top(); if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function - restoreVarState(callStack.pop().savedVars); + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); + callStack.pop() + //restoreVarState(callStack.pop().savedVars); } else { - // save existing variable state and set args as local variables + // pass supplied args to the function call through the call stack var args = parseArgs(argSpec); - var savedVars = getVarStateFor(args); - setVars(args); + // saved vars will be populated by the function call - callStack.push({ funcIdx: funcIdx, name: funcName, args: args, returnIdx: idxHere(), - savedVars: savedVars, blockStack: new Stack() }); + callStack.push({ funcIdx: funcIdx, name: fName, args: args, returnIdx: idxHere(), + savedVars: {}, blockStack: new Stack() }); // jump to function body setNextCommand(funcIdx); } }; - Selenium.prototype.doFunction = function(funcName) + Selenium.prototype.doFunction = function(funcName, paramString) { assertRunning(); - + var params, savedVars; var funcDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx === idxHere()) { - // get parameter values + contextManager.enter(); + params = parseArgs(paramString, "suppress variable expansion"); + // caching the values of all storedVars specified in function signature. + //savedVars = getVarStateFor(params); + //activeCallFrame.savedVars = savedVars; + + // set default values supplied in function definition + setVars(params); + // overwrite local variables and defaults with the supplied values from + // the call setVars(activeCallFrame.args); } else { @@ -1300,11 +1511,11 @@ function $X(xpath, contextNode, resultType) { setNextCommand(funcDef.endIdx); } }; - Selenium.prototype.doScript = function(scrName) + Selenium.prototype.doScript = function(scrName, paramString) { $$.LOG.warn("The script command has been deprecated and will be removed in future releases." + " Please use function instead."); - Selenium.prototype.doFunction(scrName); + Selenium.prototype.doFunction(scrName, paramString); }; Selenium.prototype.doReturn = function(value) { returnFromFunction(null, value); @@ -1322,15 +1533,19 @@ function $X(xpath, contextNode, resultType) { if (transitionBubbling(Stack.isFunctionBlock)) { return; } + var ret; var endDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx !== endDef.funcIdx) { // no active call, we're just skipping around a function block } else { - if (returnVal) { storedVars._result = evalWithVars(returnVal); } + if (returnVal) { ret = evalWithVars(returnVal); } + contextManager.exit(); + storedVars._result = ret; activeCallFrame.isReturning = true; // jump back to call command + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); setNextCommand(activeCallFrame.returnIdx); } } @@ -1341,13 +1556,73 @@ function $X(xpath, contextNode, resultType) { if (transitionBubbling()) { return; } - // intercept command processing and simply stop test execution instead of executing the next command - $$.fn.interceptOnce(editor.selDebugger.runner.currentTest, "resume", $$.handleAsExitTest); + // intercept command processing and simply stop test execution instead of executing the next command + if(globalContext.onServer === true) { + $$.fn.interceptOnce(htmlTestRunner.currentTest, "resume", $$.handleAsExitTest); + } else { + $$.fn.interceptOnce(editor.selDebugger.runner.currentTest, "resume", $$.handleAsExitTest); + } }; // ========= storedVars management ========= + + Selenium.prototype.doStoreGlobal = function(value, varName) { + storedVarsGlobal[varName] = value; + }; + + Selenium.prototype.doStoreEvalGlobal = function(value, varName) { + var val = evalWithVars(String(value)); + storedVarsGlobal[varName] = val; + }; + + Selenium.prototype.doStoreGlobalText = function(target, varName) { + var element = this.page().findElement(target); + storedVarsGlobal[varName] = getText(element); + }; + + Selenium.prototype.doStoreGlobalAttribute = function(target, varName) { + storedVarsGlobal[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreLocal = function(value, varName) { + storedVarsLocal[varName] = value; + }; + + Selenium.prototype.doStoreEvalLocal = function(value, varName) { + var val = evalWithVars(String(value)); + storedVarsLocal[varName] = val; + }; + + Selenium.prototype.doStoreLocalText = function(target, varName) { + var element = this.page().findElement(target); + storedVarsLocal[varName] = getText(element); + }; + + Selenium.prototype.doStoreLocalAttribute = function(target, varName) { + storedVarsLocal[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreAt = function(value, varName) { + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + + Selenium.prototype.doStoreEvalAt = function(value, varName) { + var val = evalWithVars(String(value)); + contextManager.storeAtClosestContextWithPropName(varName, val); + }; + + Selenium.prototype.doStoreAtText = function(target, varName) { + var element = this.page().findElement(target); + var value = getText(element); + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + Selenium.prototype.doStoreAtAttribute = function(target, varName) { + var value = this.page().findAttribute(target); + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + function evalWithVars(expr) { var result = null; try { @@ -1360,15 +1635,37 @@ function $X(xpath, contextNode, resultType) { } return result; } - - function parseArgs(argSpec) { // comma-sep -> new prop-set + /** + * Parses a string of comma separated args that may contain assignments with + * equal signs. + * @param {String} argSpec The string representing arguments. + * @param {Null|Any} suppressEval If this is set to any truthy value then the + * values side of any arguments will not be evaluated with respect to the + * stored variables. + * @returns {Object} Returns an object whose properties are argument names and + * whose property values are the arguments values. If no value was supplied + * then the property will exist but it will be set to undefined. + * @example + * // storedVariables.bat = "XXXXXXX"; + * parseArgs('foo="bar",baz=bat'); + * // returns {foo:"bar", baz:"XXXXXXX"} + * parseArgs('foo="bar",baz=bat', "suppress eval"); + * // returns {foo:"bar", baz:"bat"} + */ + function parseArgs(argSpec, suppressEval) { // comma-sep -> new prop-set var args = {}; var parms = iexpr.splitList(argSpec, ","); var i; for (i = 0; i < parms.length; i++) { var keyValue = iexpr.splitList(parms[i], "="); validateName(keyValue[0], "parameter"); - args[keyValue[0]] = evalWithVars(keyValue[1]); + // boolean values suck, let me put any arbitrary string as the arg + // like "suppress variable expansion" so I can be clear about my intent. + if(suppressEval) { + args[keyValue[0]] = keyValue[1]; + } else { + args[keyValue[0]] = evalWithVars(keyValue[1]); + } } return args; } @@ -1377,11 +1674,20 @@ function $X(xpath, contextNode, resultType) { var i; for (i = 0; i < names.length; i++) { if (!storedVars[names[i]]) { - storedVars[names[i]] = null; + storedVars[names[i]] = undefined; } } } } + /** + * Sets the values of existing `args` properties to match `storedVars` + * @param {Object} args A simple value store where properties represent the + * the names of arguments and their values are the default values of those + * properties. If those same properties exist on `storedVars` they will be + * overwritten in the output object. + * @returns {Object} returns a simple object that can be used as `this` in + * `fn.call` and `fn.apply` etc. + */ function getVarStateFor(args) { // storedVars(prop-set) -> new prop-set var savedVars = {}; var varname; @@ -1390,6 +1696,13 @@ function $X(xpath, contextNode, resultType) { } return savedVars; } + /** + * Gets links to the storedVars specified. + * @param {Array} names An array of strings representing the storedVars + * properties that you want to copy/link to. + * @returns {Object} returns a simple object that can be used as `this` in + * `fn.call` and `fn.apply` etc. + */ function getVarState(names) { // storedVars(names) -> new prop-set var savedVars = {}; if (names) { @@ -1400,6 +1713,14 @@ function $X(xpath, contextNode, resultType) { } return savedVars; } + /** + * Overwrites values in storedVars with values supplied. + * @param {Object} args A simple value store where properties represent the + * the names of arguments and their values are the default values of those + * properties. If those same properties exist on `storedVars` they will be + * overwritten. + * @returns {Null} returns nothing. + */ function setVars(args) { // prop-set -> storedVars var varname; for (varname in args) { @@ -1504,7 +1825,16 @@ function $X(xpath, contextNode, resultType) { this.load = function(filepath) { var fileReader = new FileReader(); - var fileUrl = urlFor(filepath); + var fileUrl; + // in order to not break existing tests the IDE will still use urlFor, + // on the server it just breaks things. Data can be anywhere on the net, + // accessible through proper CORS headers. + if(globalContext.onServer === true) { + fileUrl = filepath; + } else { + fileUrl = urlFor(filepath); + } + var xmlHttpReq = fileReader.getDocumentSynchronous(fileUrl); $$.LOG.info("Reading from: " + fileUrl); @@ -1598,7 +1928,16 @@ function $X(xpath, contextNode, resultType) { this.load = function(filepath) { var fileReader = new FileReader(); - var fileUrl = urlFor(filepath); + var fileUrl; + // in order to not break existing tests the IDE will still use urlFor, + // on the server it just breaks things. Data can be anywhere on the net, + // accessible through proper CORS headers. + if(globalContext.onServer === true) { + fileUrl = filepath; + } else { + fileUrl = urlFor(filepath); + } + var xmlHttpReq = fileReader.getDocumentSynchronous(fileUrl); $$.LOG.info("Reading from: " + fileUrl); @@ -1624,7 +1963,7 @@ function $X(xpath, contextNode, resultType) { return; } varsetIdx++; - $$.LOG.debug(varsetIdx + ") " + serializeJson(varsets[curVars])); // log each name & value + $$.LOG.debug(varsetIdx + ") " + JSON.stringify(varsets[curVars])); // log each name & value var expected = countAttrs(varsets[0]); var found = countAttrs(varsets[curVars]); @@ -1673,10 +2012,10 @@ function $X(xpath, contextNode, resultType) { } //- format the given JSON object for display - function serializeJson(obj) { - var json = uneval(obj); - return json.substring(1, json.length-1); - } + //function serializeJson(obj) { + // var json = uneval(obj); + // return json.substring(1, json.length-1); + //} } function urlFor(filepath) { @@ -1701,7 +2040,12 @@ function $X(xpath, contextNode, resultType) { // htmlSuite mode of SRC? TODO is there a better way to decide whether in SRC mode? if (window.location.href.indexOf("selenium-server") >= 0) { $$.LOG.debug("FileReader() is running in SRC mode"); - absUrl = absolutify(url, htmlTestRunner.controlPanel.getTestSuiteName()); + // there's no need to absolutify the url, the browser will do that for you + // when you make the request. The data may reside anywhere on the site, or + // within the "virtual directory" created by the selenium server proxy. + // I don't want to limit the ability to parse files that actually exist on + // the site, like sitemaps or JSON responses to api calls. + absUrl = url; } else { absUrl = absolutify(url, selenium.browserbot.baseUrl); diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selenium-executionloop-handleAsTryBlock.js b/sel-blocks-fx_xpi/chrome/content/extensions/selenium-executionloop-handleAsTryBlock.js index 32560b8..71f84b2 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selenium-executionloop-handleAsTryBlock.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selenium-executionloop-handleAsTryBlock.js @@ -37,10 +37,17 @@ function isManaged(e) { var interceptFrame = $$.fn.getInterceptTop(); + var out = false; if (e.constructor.name == "AssertResult") { e = new Error(e.failureMessage); } - return (interceptFrame && interceptFrame.attrs.manageError(e)); + try { + out = (interceptFrame && interceptFrame.attrs.manageError(e)); + } catch (ignore) { + // if there was an error trying to see if the error is managed, + // then it is not managed. + } + return out; } }; diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/xpath-processing.js b/sel-blocks-fx_xpi/chrome/content/extensions/xpath-processing.js index b73891d..812c488 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/xpath-processing.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/xpath-processing.js @@ -6,19 +6,56 @@ $$.xp = { - // Evaluate an xpathExpression against the given document object. - // The document is also the starting context, unless a contextNode is provided. - // Results are in terms of the most natural type, unless resultType specified. + /** + * Evaluate an xpathExpression against the given document object. + * @param {HTMLDOMDocument|Null} doc The document to evaluate the xpath expression + * against. Defaults to the document under test if it has the evaluate method, + * otherwise it uses the evaluate method from the selenium test runner window + * provided by the library loaded into selenium. + * @param {String} xpath The xpath expression to evaluate. + * @param {HTMLElement|Null} contextNode The effective root element for the + * xpath expression. Defaults to the document under test, falling back to + * the library loaded by selenium. + * @param {Number|Null} resultType The desired type of xpath result. + * constants may be used instead of numbers. Defaults to + * `XPathResult.ANY_TYPE`. + * @see https://developer.mozilla.org/en-US/docs/XPathResult + * @param {Function|Null} namespaceResolver The namespace resolver used to disambiguate + * namespaced elements in xhtml and xml docs. It will receive one argument: + * the (String) namespace prefix on the element and, it must return the + * string identifying the namespace that the element belongs to. In HTML + * this is usually null because nobody is using namespaces in HTML, no + * no matter how handy they are... + * @param {XPathResult|Null} resultObj Previous results from evaluating + * xpath expressions. + * @returns {XPathResult} Returns the XPathResult object containing the + * nodes found by the given query and specs. Will use the given `resultObj` + * if not null. + */ evaluateXpath: function(doc, xpath, contextNode, resultType, namespaceResolver, resultObj) { + var windowUnderTest, evaluator, isResultObjProvided, result; + + windowUnderTest = selenium.browserbot.getCurrentWindow(); + evaluator = doc || windowUnderTest.document; + contextNode = contextNode || evaluator; + resultType = resultType || XPathResult.ANY_TYPE; + isResultObjProvided = (resultObj != null); + + // The server can run tests against many different browsers. We have to + // feature test for document.evaluate in the context of the application + // under test. + if(typeof windowUnderTest.document.evaluate !== 'function') { + evaluator = document; + } + $$.xp.logXpathEval(doc, xpath, contextNode); - var isResultObjProvided = (resultObj != null); try { - var result = doc.evaluate( + result = evaluator.evaluate( xpath - , contextNode || doc + , contextNode , namespaceResolver - , resultType || XPathResult.ANY_TYPE + , resultType , resultObj); $$.LOG.trace("XPATH Result: " + $$.xp.fmtXpathResultType(result) + " : " + xpath); } @@ -27,9 +64,9 @@ //$$.LOG.traceback(err); throw err; } - if (isResultObjProvided) + if (isResultObjProvided) { result = resultObj; - + } return result; } diff --git a/sel-blocksTests/.gitignore b/sel-blocksTests/.gitignore new file mode 100644 index 0000000..da31fa8 --- /dev/null +++ b/sel-blocksTests/.gitignore @@ -0,0 +1,4 @@ +#1.1 Do NOT ignore file pattern in any subdirectory +!*/user-extensions.js +#1.2 ...only ignore it in the current directory +/user-extensions.js \ No newline at end of file diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html new file mode 100644 index 0000000..3eb13b0 --- /dev/null +++ b/sel-blocksTests/CallGlobalFunction.html @@ -0,0 +1,40 @@ + + + + + +CallGlobalFunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;not set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;not set
+ + diff --git a/sel-blocksTests/CallGlobalFunctionNesting.html b/sel-blocksTests/CallGlobalFunctionNesting.html new file mode 100644 index 0000000..da7c32f --- /dev/null +++ b/sel-blocksTests/CallGlobalFunctionNesting.html @@ -0,0 +1,47 @@ + + + + + + +CallGlobalFunctionNesting + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunctionNesting
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;not set
assertEvalglobalStoredVars.aGlobalVar;reset
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions2.setGlobalVar2
assertEvalglobalStoredVars.aGlobalVar;not set
+ + diff --git a/sel-blocksTests/DefineFunctionParameters - Base.html b/sel-blocksTests/DefineFunctionParameters - Base.html new file mode 100644 index 0000000..a7b8cf5 --- /dev/null +++ b/sel-blocksTests/DefineFunctionParameters - Base.html @@ -0,0 +1,81 @@ + + + + + + +DefineFunctionParameters - Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - Base
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionbobx,y
assertEval"${x}" === "overwritten"true
assertEvalstoredVars.y === undefinedtrue
endFunction
callbobx="overwritten"
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEvalstoredVars.y === undefinedfalse
assertEval"${y}" === "original";true
+ + diff --git a/sel-blocksTests/DefineFunctionParameters - With Default Values.html b/sel-blocksTests/DefineFunctionParameters - With Default Values.html new file mode 100644 index 0000000..cbf9f1d --- /dev/null +++ b/sel-blocksTests/DefineFunctionParameters - With Default Values.html @@ -0,0 +1,249 @@ + + + + + + +DefineFunctionParameters - With Default Values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - With Default Values
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionleakTestx="fn default x",y="fn default y"
storeoverwrittenx
storeoverwritteny
endFunction
functiondefaultsTestx="fn default x",y="fn default y"
assertEval${x} === "fn default x"true
store"overwritten"x
assertEval${x} === "overwritten"true
assertEval${y} === "fn default y"true
store"overwritten"y
assertEval${y} === "overwritten"true
endFunction
calldefaultsTest
callleakTest
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTesty = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten", y = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
+ + diff --git a/sel-blocksTests/Function - Can Return Value.html b/sel-blocksTests/Function - Can Return Value.html new file mode 100644 index 0000000..878ec6d --- /dev/null +++ b/sel-blocksTests/Function - Can Return Value.html @@ -0,0 +1,41 @@ + + + + + + +Function - Can Return Value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Function - Can Return Value
functionreturnsValue
return"banana"
endFunction
callreturnsValue
assertEval"${_result}" === "banana"true
+ + diff --git a/sel-blocksTests/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html new file mode 100644 index 0000000..81e6a49 --- /dev/null +++ b/sel-blocksTests/GlobalFunctions.html @@ -0,0 +1,35 @@ + + + + + +GlobalFunctions + + + + + + + + + + + + + + + + + + + + + + + + + + +
functions
getEvalglobalStoredVars = {};
functionsetGlobalVar
getEvalglobalStoredVars.aGlobalVar = "not set";
endFunction
+ + diff --git a/sel-blocksTests/GlobalFunctions2.html b/sel-blocksTests/GlobalFunctions2.html new file mode 100644 index 0000000..4e5de12 --- /dev/null +++ b/sel-blocksTests/GlobalFunctions2.html @@ -0,0 +1,37 @@ + + + + + + +GlobalFunctions2 + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobalFunctions2
functionsetGlobalVar2
getEvalglobalStoredVars.aGlobalVar = "is set";
callGlobalFunctions.setGlobalVar
endFunction
+ + diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html new file mode 100644 index 0000000..c171f0e --- /dev/null +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -0,0 +1,27 @@ + + + + + + Test Suite + + + + + + + + + + + + + + + + + + +
Test Suite
CreateGlobalVars
GlobalFunctions
GlobalFunctions 2
CallGlobalFunction
DefineFunctionParameters - Base
DefineFunctionParameters - With Default Values
StoreLocal - Function Scope
StoreGlobal - Function Scope
StoreGlobal - While Scope
StoreLocal - While Scope
Store - Behaves as StoreLocal
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
+ + diff --git a/sel-blocksTests/README.html b/sel-blocksTests/README.html index d7ec61c..02d230c 100644 --- a/sel-blocksTests/README.html +++ b/sel-blocksTests/README.html @@ -14,7 +14,7 @@ open - file:///C:/projects/selenium/selblocks/SelBlocks/sel-blocksTests/_SelBlocks-testpage.html + http://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.html diff --git a/sel-blocksTests/Store - Behaves as StoreLocal.html b/sel-blocksTests/Store - Behaves as StoreLocal.html new file mode 100644 index 0000000..a917370 --- /dev/null +++ b/sel-blocksTests/Store - Behaves as StoreLocal.html @@ -0,0 +1,101 @@ + + + + + + +Store - Behaves as StoreLocal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store - Behaves as StoreLocal
functionblockScopeVars
storethis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + diff --git a/sel-blocksTests/StoreAt - Function Scope Nesting.html b/sel-blocksTests/StoreAt - Function Scope Nesting.html new file mode 100644 index 0000000..d428d44 --- /dev/null +++ b/sel-blocksTests/StoreAt - Function Scope Nesting.html @@ -0,0 +1,129 @@ + + + + + + +StoreAt - Function Scope Nesting + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - Function Scope Nesting
functionstorel
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
endFunction
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
callstorel
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + diff --git a/sel-blocksTests/StoreAt - While Scope Nesting.html b/sel-blocksTests/StoreAt - While Scope Nesting.html new file mode 100644 index 0000000..7185ae6 --- /dev/null +++ b/sel-blocksTests/StoreAt - While Scope Nesting.html @@ -0,0 +1,140 @@ + + + + + + +StoreAt - While Scope Nesting + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - While Scope Nesting
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
storeLocal3x
whilex !== 0
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
storeEvalLocalx -= 1
endWhile
deleteVarx
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + diff --git a/sel-blocksTests/StoreGlobal - Function Scope.html b/sel-blocksTests/StoreGlobal - Function Scope.html new file mode 100644 index 0000000..5c61fc5 --- /dev/null +++ b/sel-blocksTests/StoreGlobal - Function Scope.html @@ -0,0 +1,89 @@ + + + + + + +StoreGlobal - Function Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - Function Scope
functionblockScopeVars
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endFunction
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + diff --git a/sel-blocksTests/StoreGlobal - While Scope.html b/sel-blocksTests/StoreGlobal - While Scope.html new file mode 100644 index 0000000..80d8560 --- /dev/null +++ b/sel-blocksTests/StoreGlobal - While Scope.html @@ -0,0 +1,95 @@ + + + + + + +StoreGlobal - While Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - While Scope
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
store1i
whilei > 0
store0i
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endWhile
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + diff --git a/sel-blocksTests/StoreLocal - Base.html b/sel-blocksTests/StoreLocal - Base.html new file mode 100644 index 0000000..cca78b6 --- /dev/null +++ b/sel-blocksTests/StoreLocal - Base.html @@ -0,0 +1,62 @@ + + + + + + +StoreLocal - Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storethis is stored globallyg
storeLocalthis is stored locallyl
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVars.l === "this is stored locally"true
endFunction
callblockScopeVars
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVars.l === "this is stored locally"false
+ + diff --git a/sel-blocksTests/StoreLocal - Function Scope.html b/sel-blocksTests/StoreLocal - Function Scope.html new file mode 100644 index 0000000..944f809 --- /dev/null +++ b/sel-blocksTests/StoreLocal - Function Scope.html @@ -0,0 +1,101 @@ + + + + + + +StoreLocal - Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + diff --git a/sel-blocksTests/StoreLocal - While Scope.html b/sel-blocksTests/StoreLocal - While Scope.html new file mode 100644 index 0000000..cf71f8f --- /dev/null +++ b/sel-blocksTests/StoreLocal - While Scope.html @@ -0,0 +1,107 @@ + + + + + + +StoreLocal - While Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - While Scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
store1i
whilei > 0
store0i
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endWhile
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 27faa8c..990e79a 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -11,20 +11,63 @@ README eval branching -if -try +if-1 +if-2 +if-3 +try - noop +try - finally with no error +try - catch but no error +try - catch specific error +try - catch specific error then finally +try - catch throw finally throw +try - bubble up to catch ALL +try - bubble up to catch ALL via finally +try - bubble up out of noop try to catch specific error +try - bubble up to catch specific error +try - bubble up to catch specific error via finally +try - throw catch rethrow +try - bubble out of nested function calls +try - command bubbling break with finally +try - command bubbling intra try break +try - command bubbling continue with finally +try - command bubbling intra try continue +try - command bubbling error replaced by return +try - command bubbling error replaced by return 2 +try - command bubbling return replaced by error +try - exitTest with finally processing +try - try without matching catch while for foreach foreach-xpath forjson forxml -continue-break +continue-break 1 +continue-break 2 +continue-break 3 +continue-break 4 nested-loops function function-recursive -issue#2-function -exitTest +issue-2-function +exitTest - base case +exitTest - from within a loop +exitTest - from within a function +GlobalFunctions +CallGlobalFunction +DefineFunctionParameters - Base +DefineFunctionParameters - With Default Values +StoreLocal - Function Scope +StoreGlobal - Function Scope +StoreGlobal - While Scope +StoreLocal - While Scope +Store - Behaves as StoreLocal +Function - Can Return Value +StoreAt - Function Scope Nesting +StoreAt - While Scope Nesting +sendkeys keys are preserved +GlobalFunctions2 +CallGlobalFunctionNesting diff --git a/sel-blocksTests/branching.html b/sel-blocksTests/branching.html index b3ea303..68f351d 100644 --- a/sel-blocksTests/branching.html +++ b/sel-blocksTests/branching.html @@ -108,7 +108,7 @@ expectError - "random is not defined" + /.*random.* (is not |is un)defined/ diff --git a/sel-blocksTests/continue-break 1.html b/sel-blocksTests/continue-break 1.html new file mode 100644 index 0000000..e38c96d --- /dev/null +++ b/sel-blocksTests/continue-break 1.html @@ -0,0 +1,87 @@ + + + + + + +continue-break 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 1
resetEmitted
deleteVarsf
forf=3; f <= 9; f++
continuef == 6
iff > 6
iff == 7
continue
else
break
endIf
endIf
emit"iter=${f}"
endFor
assertEmitted"iter=3~iter=4~iter=5"
+ + diff --git a/sel-blocksTests/continue-break 2.html b/sel-blocksTests/continue-break 2.html new file mode 100644 index 0000000..22367f4 --- /dev/null +++ b/sel-blocksTests/continue-break 2.html @@ -0,0 +1,58 @@ + + + + + + +continue-break 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 2
resetEmitted
store0i
whilei++ < 10
continuei==3
breaki==5
emit"iter=${i}"
endWhile
assertEmitted"iter=1~iter=2~iter=4"
+ + diff --git a/sel-blocksTests/continue-break 3.html b/sel-blocksTests/continue-break 3.html new file mode 100644 index 0000000..bd88c8c --- /dev/null +++ b/sel-blocksTests/continue-break 3.html @@ -0,0 +1,53 @@ + + + + + + +continue-break 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 3
resetEmitted
foreachfe"dilbert","dogbert","wally"
continuefe=="dogbert"
breakfe=="wally"
emit"iter=${fe}"
endForeach
assertEmitted"iter=dilbert"
+ + diff --git a/sel-blocksTests/continue-break 4.html b/sel-blocksTests/continue-break 4.html new file mode 100644 index 0000000..164815b --- /dev/null +++ b/sel-blocksTests/continue-break 4.html @@ -0,0 +1,77 @@ + + + + + + +continue-break 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 4
resetEmitted
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
forXml${forXmlFileName}
continuexname=="dogbert"
breakxname=="wally"
emit"iter=${xname}"
endForXml
assertEmitted"iter=dilbert"
+ + diff --git a/sel-blocksTests/continue-break.html b/sel-blocksTests/continue-break.html index 103dfb2..d80c658 100644 --- a/sel-blocksTests/continue-break.html +++ b/sel-blocksTests/continue-break.html @@ -11,6 +11,31 @@ foreach + + if + globalContext.onServer === true + + + + store + ../data/forxml.xml + forXmlFileName + + + else + + + + + store + data/forxml.xml + forXmlFileName + + + endIf + + + resetEmitted @@ -169,7 +194,7 @@ forXml - data/forxml.xml + ${forXmlFileName} diff --git a/sel-blocksTests/exitTest - base case.html b/sel-blocksTests/exitTest - base case.html new file mode 100644 index 0000000..58e6a12 --- /dev/null +++ b/sel-blocksTests/exitTest - base case.html @@ -0,0 +1,32 @@ + + + + + + +exitTest - base case + + + + + + + + + + + + + + + + + + + + + + +
exitTest - base case
resetEmitted
exitTest
throw"shouldn't happen"
+ + diff --git a/sel-blocksTests/exitTest - from within a function.html b/sel-blocksTests/exitTest - from within a function.html new file mode 100644 index 0000000..7e4407d --- /dev/null +++ b/sel-blocksTests/exitTest - from within a function.html @@ -0,0 +1,43 @@ + + + + + + +exitTest - from within a function + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a function
calldoSubExit
throw"shouldn't happen"
functiondoSubExit
exitTest
endFunctiondoSubExit
+ + diff --git a/sel-blocksTests/exitTest - from within a loop.html b/sel-blocksTests/exitTest - from within a loop.html new file mode 100644 index 0000000..6ef3a30 --- /dev/null +++ b/sel-blocksTests/exitTest - from within a loop.html @@ -0,0 +1,57 @@ + + + + + + +exitTest - from within a loop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a loop
fori=0; i < 5; i++
ifi == 3
exitTest
endIf
ifi === 3
throw"This test should exit when the increment gets to 3, and this should never be thrown."
endIf
endFor
+ + diff --git a/sel-blocksTests/forjson.html b/sel-blocksTests/forjson.html index 78b931b..468af1f 100644 --- a/sel-blocksTests/forjson.html +++ b/sel-blocksTests/forjson.html @@ -11,6 +11,31 @@ foreach + + if + globalContext.onServer === true + + + + store + ../data/forjson.json + forJsonFileName + + + else + + + + + store + data/forjson.json + forJsonFileName + + + endIf + + + resetEmitted @@ -29,7 +54,7 @@ forJson - data/forjson.json + ${forJsonFileName} @@ -50,7 +75,7 @@ loadJsonVars - data/forjson.json + ${forJsonFileName} jname == "dogbert" @@ -84,7 +109,7 @@ loadJsonVars - data/forjson.json + ${forJsonFileName} @@ -95,7 +120,7 @@ loadJsonVars - data/forjson.json + ${forJsonFileName} "flubber" diff --git a/sel-blocksTests/forxml.html b/sel-blocksTests/forxml.html index 21859ca..f1ba641 100644 --- a/sel-blocksTests/forxml.html +++ b/sel-blocksTests/forxml.html @@ -3,7 +3,7 @@ - + forxml @@ -11,6 +11,31 @@ foreach + + if + globalContext.onServer === true + + + + store + ../data/forxml.xml + forXmlFileName + + + else + + + + + store + data/forxml.xml + forXmlFileName + + + endIf + + + resetEmitted @@ -29,7 +54,7 @@ forXml - data/forxml.xml + ${forXmlFileName} @@ -50,7 +75,7 @@ loadXmlVars - data/forxml.xml + ${forXmlFileName} xname == "dogbert" @@ -66,7 +91,7 @@ loadXmlVars - data/forxml.xml + ${forXmlFileName} xname == "dogbert" @@ -89,7 +114,7 @@ loadXmlVars - data/forxml.xml + ${forXmlFileName} @@ -100,7 +125,7 @@ loadXmlVars - data/forxml.xml + ${forXmlFileName} "flubber" diff --git a/sel-blocksTests/function.html b/sel-blocksTests/function.html index 5642472..22c8074 100644 --- a/sel-blocksTests/function.html +++ b/sel-blocksTests/function.html @@ -11,20 +11,15 @@ subtest - - resetEmitted - - - deleteVars sname, srole - emit - "START ${sname} ${srole}" - + assertEval + "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}" + true @@ -32,6 +27,16 @@ doSomething sname = "dilbert,Q", srole = "goof" + + assertEval + "${_result}" === "sname=dilbert,Q,srole=goof" + true + + + deleteVars + sname, srole + + function @@ -39,7 +44,7 @@ sname - emit + return "sname=${sname},srole=${srole}" @@ -49,16 +54,41 @@ + + deleteVars + sname, srole + + call doSomething sname = "dogbert", srole = "woof" + + assertEval + "${_result}" === "sname=dogbert,srole=woof" + true + + + deleteVars + sname, srole + + call doSomething sname = "ratbert", srole = "squeak" + + assertEval + "${_result}" === "sname=ratbert,srole=squeak" + true + + + deleteVars + sname, srole + + foreach @@ -71,21 +101,25 @@ sname = sname, srole = "super=user" - endForeach - - + assertEval + "${_result}" === "sname=${sname},srole=super=user" + true - emit - "DONE ${sname} ${srole}" + deleteVars + sname, srole - - assertEmitted - "START $" + "{sname} $" + "{srole}~sname=dilbert,Q,srole=goof~sname=dogbert,srole=woof~sname=ratbert,srole=squeak~sname=asok,srole=super=user~sname=alice,srole=super=user~DONE $" + "{sname} $" + "{srole}" + endForeach + + + assertEval + "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}" + true + @@ -100,8 +134,8 @@ - resetEmitted - + deleteVars + sname, srole @@ -110,7 +144,7 @@ sname - emit + return "sname=${sname},srole=${srole}" @@ -125,8 +159,13 @@ sname = "wally", srole = "lazy" - assertEmitted - "sname=wally,srole=lazy" + assertEval + "${_result}" === "sname=wally,srole=lazy" + true + + + deleteVars + sname, srole diff --git a/sel-blocksTests/if-1.html b/sel-blocksTests/if-1.html new file mode 100644 index 0000000..6c98a26 --- /dev/null +++ b/sel-blocksTests/if-1.html @@ -0,0 +1,234 @@ + + + + + + +if-1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-1
resetEmitted
emit"BEFORE"
iftrue
emit"truthy"
endIf
iffalse
emit"falsey"
endIf
iftrue
emit"A"
else
emit"B"
endIf
iffalse
emit"X"
else
emit"Y"
endIf
iffalse
emit"false teeth"
else
iftrue
emit"truthF"
else
emit"false false"
endIf
endIf
if"dilbert".isOneOf("dogbert","dilbert","wally")
emit"office mate"
endIf
if"dilbert".isOneOf("ratbert","alice","asok")
emit"mate"
else
emit"coffee mate"
endIf
if"mordac".isOneOf("bob the dinosaur","garbage man","mordac")
emit"cell mate"
else
emit"don't wait"
endIf
emit"AFTER"
assertEmitted"BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER"
+ + diff --git a/sel-blocksTests/if-2.html b/sel-blocksTests/if-2.html new file mode 100644 index 0000000..4382d28 --- /dev/null +++ b/sel-blocksTests/if-2.html @@ -0,0 +1,187 @@ + + + + + + +if-2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-2
resetEmitted
iftrue
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-a1y"
elseIftrue
emit"else-a2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-b1y"
elseIftrue
emit"elseIf-b2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-y"
else
emit"else-y"
endIf
assertEmitted"if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y"
+ + diff --git a/sel-blocksTests/if-3.html b/sel-blocksTests/if-3.html new file mode 100644 index 0000000..0991b0e --- /dev/null +++ b/sel-blocksTests/if-3.html @@ -0,0 +1,93 @@ + + + + + + +if-3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-3
resetEmitted
foreachi2, 0, 1, 4, 3, 5
ifi == 0
emit"if-${i}"
elseIfi == 1
emit"elseIf-${i}"
elseIfi == 2
emit"elseIf-${i}"
elseIfi == 3
emit"elseIf-${i}"
else
emit"else-${i}"
endIf
endForeach
assertEmitted"elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5"
+ + diff --git a/sel-blocksTests/issue#2-function.html b/sel-blocksTests/issue-2-function.html similarity index 100% rename from sel-blocksTests/issue#2-function.html rename to sel-blocksTests/issue-2-function.html diff --git a/sel-blocksTests/nested-loops.html b/sel-blocksTests/nested-loops.html index b682354..b2c623d 100644 --- a/sel-blocksTests/nested-loops.html +++ b/sel-blocksTests/nested-loops.html @@ -119,7 +119,7 @@ assertEmitted - "START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 0" + "START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2" diff --git a/sel-blocksTests/sendkeys keys are preserved.html b/sel-blocksTests/sendkeys keys are preserved.html new file mode 100644 index 0000000..bb971fe --- /dev/null +++ b/sel-blocksTests/sendkeys keys are preserved.html @@ -0,0 +1,32 @@ + + + + + + +sendkeys keys are preserved + + + + + + + + + + + + + + + + + + + + + + +
sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ + diff --git a/sel-blocksTests/try - bubble out of nested function calls.html b/sel-blocksTests/try - bubble out of nested function calls.html new file mode 100644 index 0000000..bd12a70 --- /dev/null +++ b/sel-blocksTests/try - bubble out of nested function calls.html @@ -0,0 +1,180 @@ + + + + + + +try - bubble out of nested function calls + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble out of nested function calls
log"-- bubble out of nested function calls --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-invoke
emit"trying"
emit"calling"
callsubBubn = 0
assertEval"this command should not be reached, due error thrown in function"
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-invoke
assertEvalselblocks.tcf.nestingLevel-1
functionsubBubn
trytcf-inner
emit"${n}) trying-inner"
ifn < 2
emit"${n}) calling"
callsubBubn = n+1
else
emit"${n}) throwing"
throw"blamo"
endIf
finally
emit"${n}) finally"
endTrytcf-inner
assertEvalselblocks.tcf.nestingLevel0
endFunction
emit"/])"
assertEmitted"([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])"
+ + diff --git a/sel-blocksTests/try - bubble up out of noop try to catch specific error.html b/sel-blocksTests/try - bubble up out of noop try to catch specific error.html new file mode 100644 index 0000000..aee57d7 --- /dev/null +++ b/sel-blocksTests/try - bubble up out of noop try to catch specific error.html @@ -0,0 +1,131 @@ + + + + + + +try - bubble up out of noop try to catch specific error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up out of noop try to catch specific error
log"-- bubble out of no-op try to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trynoop-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryop-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
endTryop-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrynoop-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch ALL via finally.html b/sel-blocksTests/try - bubble up to catch ALL via finally.html new file mode 100644 index 0000000..bb14827 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch ALL via finally.html @@ -0,0 +1,136 @@ + + + + + + +try - bubble up to catch ALL via finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL via finally
log"-- bubble up to catch ALL via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-allfin-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-allfin-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-allfin-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-allfin-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch ALL.html b/sel-blocksTests/try - bubble up to catch ALL.html new file mode 100644 index 0000000..4a92a44 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch ALL.html @@ -0,0 +1,126 @@ + + + + + + +try - bubble up to catch ALL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL
log"-- bubble up to catch ALL --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-all-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-all-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
endTryt-all-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-all-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch specific error via finally.html b/sel-blocksTests/try - bubble up to catch specific error via finally.html new file mode 100644 index 0000000..ce43952 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch specific error via finally.html @@ -0,0 +1,141 @@ + + + + + + +try - bubble up to catch specific error via finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error via finally
log"-- bubble up to catch specific error via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch specific error.html b/sel-blocksTests/try - bubble up to catch specific error.html new file mode 100644 index 0000000..a7af661 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch specific error.html @@ -0,0 +1,131 @@ + + + + + + +try - bubble up to catch specific error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error
log"-- bubble up to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])"
+ + diff --git a/sel-blocksTests/try - catch but no error.html b/sel-blocksTests/try - catch but no error.html new file mode 100644 index 0000000..86c37a3 --- /dev/null +++ b/sel-blocksTests/try - catch but no error.html @@ -0,0 +1,79 @@ + + + + + + +try - catch but no error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch but no error
log"-- try/catch, but no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc0
emit"trying"
catch
assertEval"should NEVER enter this catch block due to no error"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + diff --git a/sel-blocksTests/try - catch specific error then finally.html b/sel-blocksTests/try - catch specific error then finally.html new file mode 100644 index 0000000..bc7c505 --- /dev/null +++ b/sel-blocksTests/try - catch specific error then finally.html @@ -0,0 +1,136 @@ + + + + + + +try - catch specific error then finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error then finally
log"-- catch specific error, then finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel-1
emit"([/"
tryt-spec-inner
emit"trying inner"
throw"blamo inner"
assertEval"this command should not be reached, due to throw"
catch/blamo inner/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-spec-inner
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
endTryt-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])"
+ + diff --git a/sel-blocksTests/try - catch specific error.html b/sel-blocksTests/try - catch specific error.html new file mode 100644 index 0000000..ce15200 --- /dev/null +++ b/sel-blocksTests/try - catch specific error.html @@ -0,0 +1,84 @@ + + + + + + +try - catch specific error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error
log"-- catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc1
throw"blamo catch ALL"
assertEval"this command should not be reached, due to thrown"
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~caught 'blamo catch ALL'~/])"
+ + diff --git a/sel-blocksTests/try - catch throw finally throw.html b/sel-blocksTests/try - catch throw finally throw.html new file mode 100644 index 0000000..cb152ec --- /dev/null +++ b/sel-blocksTests/try - catch throw finally throw.html @@ -0,0 +1,156 @@ + + + + + + +try - catch throw finally throw + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch throw finally throw
log"-- catch/throw, finally/throw --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytcf-trap
assertEvalselblocks.tcf.nestingLevel0
trytcf
emit"trying"
emit"throwing A"
throw"blamoA"
assertEval"this command should not be reached, due to thrown"
catch/blamoA/
emit"caught '" + _error.message + "'"
emit"throwing B"
throw"blamoB"
finally
emit"finally"
emit"throwing C"
throw"blamoC"
endTry
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling break with finally.html b/sel-blocksTests/try - command bubbling break with finally.html new file mode 100644 index 0000000..4bd08df --- /dev/null +++ b/sel-blocksTests/try - command bubbling break with finally.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling, break with finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling, break with finally
log"-- command bubbling, break w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"${w}) trying"
ifw==2
emit"${w}) BREAK"
break
endIf
finally
emit"${w}) finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling continue with finally.html b/sel-blocksTests/try - command bubbling continue with finally.html new file mode 100644 index 0000000..1841938 --- /dev/null +++ b/sel-blocksTests/try - command bubbling continue with finally.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling continue with finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling continue with finally
log"-- command bubbling, continue w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"${w}) trying"
ifw==2
emit"${w}) CONTINUE"
continue
endIf
finally
emit"${w}) finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling error replaced by return 2.html b/sel-blocksTests/try - command bubbling error replaced by return 2.html new file mode 100644 index 0000000..cf8f5f3 --- /dev/null +++ b/sel-blocksTests/try - command bubbling error replaced by return 2.html @@ -0,0 +1,129 @@ + + + + + + +try - command bubbling error replaced by return 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return 2
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubB
emit"returned ${_result}"
functioncmdBubB
emit"in cmdBubB"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"throwing"
throw"short-lived error"
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to throw/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling error replaced by return.html b/sel-blocksTests/try - command bubbling error replaced by return.html new file mode 100644 index 0000000..6d1428a --- /dev/null +++ b/sel-blocksTests/try - command bubbling error replaced by return.html @@ -0,0 +1,129 @@ + + + + + + +try - command bubbling error replaced by return + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubA
emit"returned ${_result}"
functioncmdBubA
emit"in cmdBubA"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to return/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling intra try break.html b/sel-blocksTests/try - command bubbling intra try break.html new file mode 100644 index 0000000..fa9d2fa --- /dev/null +++ b/sel-blocksTests/try - command bubbling intra try break.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling intra try break + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try break
log"-- command bubbling, intra-try break --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) BREAK"
break
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) BREAK~finallying~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling intra try continue.html b/sel-blocksTests/try - command bubbling intra try continue.html new file mode 100644 index 0000000..b135e67 --- /dev/null +++ b/sel-blocksTests/try - command bubbling intra try continue.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling intra try continue + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try continue
log"-- command bubbling, intra-try continue --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) CONTINUE"
continue
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling return replaced by error.html b/sel-blocksTests/try - command bubbling return replaced by error.html new file mode 100644 index 0000000..139c160 --- /dev/null +++ b/sel-blocksTests/try - command bubbling return replaced by error.html @@ -0,0 +1,155 @@ + + + + + + +try - command bubbling return replaced by error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling return replaced by error
log"-- command bubbling, return replaced by error --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubC
emit"returned ${_result}"
functioncmdBubC
emit"in cmdBubC"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf-guardrail
assertEvalselblocks.tcf.nestingLevel0
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"throwing"
throw"this-error-replaces-return-1"
endTry
catch/this-error-replaces-return-1/
emit"caught '" + _error.message + "'"
assertEvalselblocks.tcf.nestingLevel0
endTry
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])"
+ + diff --git a/sel-blocksTests/try - exitTest with finally processing.html b/sel-blocksTests/try - exitTest with finally processing.html new file mode 100644 index 0000000..a7f0082 --- /dev/null +++ b/sel-blocksTests/try - exitTest with finally processing.html @@ -0,0 +1,89 @@ + + + + + + +try - exitTest with finally processing + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - exitTest with finally processing
log"-- exitTest w/finally processing --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryabort
emit"trying"
emit"exitTest ..."
exitTest
finally
emit"finallying"
assertEmitted"([/~trying~exitTest ...~finallying"
resetEmitted
endTryabort
assertEval"this command should not be reached, due to exitTest above"
+ + diff --git a/sel-blocksTests/try - finally with no error.html b/sel-blocksTests/try - finally with no error.html new file mode 100644 index 0000000..ec93f97 --- /dev/null +++ b/sel-blocksTests/try - finally with no error.html @@ -0,0 +1,79 @@ + + + + + + +try - finally with no error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - finally with no error
log"-- try/finally, w/no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-fin
emit"trying"
finally
emit"finally"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~finally~/])"
+ + diff --git a/sel-blocksTests/try - noop.html b/sel-blocksTests/try - noop.html new file mode 100644 index 0000000..a6cb6e9 --- /dev/null +++ b/sel-blocksTests/try - noop.html @@ -0,0 +1,69 @@ + + + + + + +try - noop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - noop
log"-- no-op try --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-noop
emit"trying"
endTryt-noop
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + diff --git a/sel-blocksTests/try - throw catch rethrow.html b/sel-blocksTests/try - throw catch rethrow.html new file mode 100644 index 0000000..3674a70 --- /dev/null +++ b/sel-blocksTests/try - throw catch rethrow.html @@ -0,0 +1,141 @@ + + + + + + +try - throw catch rethrow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - throw catch rethrow
log"-- throw, catch, rethrow --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryouter
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryinner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing blamo1"
throw"blamo1"
assertEval"this command should not be reached, due to throw"
catch/blamo1/
emit"caught '" + _error.message + "'"
emit"throwing blamo2"
throw"blamo2"
endTryinner
catch/blamo2/
emit"caught '" + _error.message + "'"
endTryouter
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])"
+ + diff --git a/sel-blocksTests/try - try without matching catch.html b/sel-blocksTests/try - try without matching catch.html new file mode 100644 index 0000000..d4edc36 --- /dev/null +++ b/sel-blocksTests/try - try without matching catch.html @@ -0,0 +1,89 @@ + + + + + + +try - try without matching catch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - try without matching catch
log"-- try without matching catch --"
resetEmitted
assertEvalselblocks.tcf.nestingLevel-1
trymiss
assertEvaltruetrue
throw"blamo will NOT be caught at all"
assertEval"this command should not be reached"
catch/will NOT catch it/
log"caught miss '" + _error.message + "'"
finally
log"finally"
endTrymiss
assertEvalselblocks.tcf.nestingLevel-1
emit"trying"
+ + diff --git a/sel-blocksTests/while.html b/sel-blocksTests/while.html index f3178df..beb7b20 100644 --- a/sel-blocksTests/while.html +++ b/sel-blocksTests/while.html @@ -76,7 +76,7 @@ assertEmitted - "START: 3~iter=3~iter=2~iter=1~END: 0" + "START: 3~iter=3~iter=2~iter=1~END: 3" diff --git a/testUserExtension/.gitignore b/testUserExtension/.gitignore new file mode 100644 index 0000000..b4cf059 --- /dev/null +++ b/testUserExtension/.gitignore @@ -0,0 +1,2 @@ +*Log* +user-extensions.js \ No newline at end of file diff --git a/testUserExtension/Proxy localhost 4444 disable.reg b/testUserExtension/Proxy localhost 4444 disable.reg new file mode 100644 index 0000000..720013d Binary files /dev/null and b/testUserExtension/Proxy localhost 4444 disable.reg differ diff --git a/testUserExtension/Proxy localhost 4444 enable.reg b/testUserExtension/Proxy localhost 4444 enable.reg new file mode 100644 index 0000000..07207ae Binary files /dev/null and b/testUserExtension/Proxy localhost 4444 enable.reg differ diff --git a/testUserExtension/README.md b/testUserExtension/README.md new file mode 100644 index 0000000..a673a1c --- /dev/null +++ b/testUserExtension/README.md @@ -0,0 +1,93 @@ +#Running Tests + +When running the tests, the user-extensions.js file is rebuilt and SelBench is + added into it. You'll need to have both projects in order to run the tests. + Place them like so on your computer: + +``` +C:\projects + \---selenium + +---selbench + | \---SelBench + | +---build + | +---selbench-fx-xpi + | | \---chrome + | | +---content + | | | \---extensions + | | \---skin + | +---selbenchTests + | +---testUserExtension + | \---user extension + | \---scripts + +---selblocks + | \---SelBlocks + | +---build + | +---notes + | +---sel-blocks-fx_xpi + | | \---chrome + | | +---content + | | | \---extensions + | | \---skin + | +---sel-blocksTests + | | \---data + | +---testUserExtension + | \---user extension + | \---scripts + +---server + chromedriver.exe + IEDriverServer.exe + selenium-server-standalone-2.43.1.jar +``` + +Then run `createSelbenchUserExtensions.cmd` + in the `SelBench\build` directory to rebuild the SelBench server + extension. After that is set up, you should be able to just run + `C:\projects\selenium\selblocks\SelBlocks\testUserExtension\runTestsOnServer.cmd` + to launch the automatic tests in firefox. + +*Run `runTestsOnServer.cmd --help` to see all the options available.* + +As soon as the automatic tests complete, the results should open in your + browser. The server should restart in debug mode and the page to the test suite + should open automatically. In order to work in debug mode your browser will + have to be configured to use the selenium server as it's proxy. By default the + host is `localhost` and the port is `4444`. It's best to use a separate profile + for running tests, especially if you want to use the web to look things up while + you debug. The selenium server can proxy https, but you have to accept the + hacked certificate from "cybervillains" in order to do it. Just make a separate + profile in firefox and you'll be fine. Don't do it in IE, the cert will take + effect for everyone, all the time, and you'll have to remember to remove the + cert when you're done so you don't get hacked and sold for parts. + +To run the automatic tests in firefox googlechrome and internet explorer do + `runTestsOnServer.cmd start-autotests all`. The results won't open + automatically though, they'll be in `SelBlocks\testUserExtension`. Presently + (selenium-standalone-server-2.43.1 2.44.0) the internet explorer doesn't + automatically have it's proxy set to localhost:4444 like it should. You'll have + to open the internet options in IE once it launches and set the proxy yourself. + Then, copy the address from the address bar and paste it into a new tab. It's + convoluted I know, but hey, the tests all go by themselves and generate + results. I suppose if you really wanted to get fancy you could use AutoHotkey + to watch for the IE window and autmatically change the settings for you. + +See also: http://selenium.googlecode.com/git-history/rc-0.9.2/website/tutorial.html + +#debugging user-extensions.js + +Run `runTestsOnServer.cmd start-debug` and the default test suite will be loaded + into the selenium test runner. The test runner will open in your default web + browser, which must be configured to use the selenium server as a proxy + (localhost:4444). You can use whatever tools you like to inspect and debug + javascript. By editing the copy of user-extensions.js that gets copied into + `/sel-blocksTests` and refreshing the test runner page, you'll be able to see + what effect your changes will have when running this extension on the server. + When you're satisfied that you know what to change, go edit the source files + in `/sel-blocks-fx_xpi/chrome/content/extensions/` and the next time that + `user-extensions.js` is built it will include your edits. It's a good idea to + install the firefox extension from source so that you can test that your + changes won't break it. + +See also: https://developer.mozilla.org/en-US/Add-ons/Setting_up_extension_development_environment +See the part about creating a firefox extension proxy file, so that you don't + have to copy paste the source into your extensions directory all the time. + \ No newline at end of file diff --git a/testUserExtension/results-firefox.html b/testUserExtension/results-firefox.html new file mode 100644 index 0000000..46bf439 --- /dev/null +++ b/testUserExtension/results-firefox.html @@ -0,0 +1,8084 @@ + +Test suite results + +

Test suite results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
result:failed
totalTime:35
numTestTotal:58
numTestPasses:57
numTestFailures:1
numCommandPasses:196
numCommandFailures:0
numCommandErrors:1
Selenium Version:2.43
Selenium Revision:.1
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test Suite
README
eval
branching
if-1
if-2
if-3
try - noop
try - finally with no error
try - catch but no error
try - catch specific error
try - catch specific error then finally
try - catch throw finally throw
try - bubble up to catch ALL
try - bubble up to catch ALL via finally
try - bubble up out of noop try to catch specific error
try - bubble up to catch specific error
try - bubble up to catch specific error via finally
try - throw catch rethrow
try - bubble out of nested function calls
try - command bubbling break with finally
try - command bubbling intra try break
try - command bubbling continue with finally
try - command bubbling intra try continue
try - command bubbling error replaced by return
try - command bubbling error replaced by return 2
try - command bubbling return replaced by error
try - exitTest with finally processing
try - try without matching catch
while
for
foreach
foreach-xpath
forjson
forxml
continue-break 1
continue-break 2
continue-break 3
continue-break 4
nested-loops
function
function-recursive
issue-2-function
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
GlobalFunctions
CallGlobalFunction
DefineFunctionParameters - Base
DefineFunctionParameters - With Default Values
StoreLocal - Function Scope
StoreGlobal - Function Scope
StoreGlobal - While Scope
StoreLocal - While Scope
Store - Behaves as StoreLocal
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
+ + +
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
README.html
+ + + + + + + + + + +
README
openhttp://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.html
+ + +
 
eval.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
eval
resetEmitted
emit"dilbert".isOneOf("dilbert","dogbert","mordac")
emit"bob".isOneOf("dilbert","dogbert","mordac")
emit"red".mapTo("primary", ["red","green","blue"])
emit"orange".mapTo("primary", ["red","green","blue"])
emit"red".translate("e", "E")
emit"red".translate(["red", "green", "blue"], ["blue", "red", "green"])
assertEmitted"true~false~primary~orange~rEd~blue"
+ + +
 
branching.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
branching
resetEmitted
emit"BEFORE"
gotoHERE
emit"A"
labelHERE
gotoIftrueTHERE
emit"B"
labelTHERE
skipNext
emit"C"
emit"AFTER"
assertEmitted"BEFORE~AFTER"
expectError"Target label 'NOWHERE' is not found"
gotoNOWHERE
expectError"Target label 'NOWHERE' is not found"
gotoIftrueNOWHERE
expectError"Requires a number > 1"
skipNext-1
expectError/.*random.* (is not |is un)defined/
skipNextrandom
+ + +
 
if-1.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-1
resetEmitted
emit"BEFORE"
iftrue
emit"truthy"
endIf
iffalse
emit"falsey"
endIf
iftrue
emit"A"
else
emit"B"
endIf
iffalse
emit"X"
else
emit"Y"
endIf
iffalse
emit"false teeth"
else
iftrue
emit"truthF"
else
emit"false false"
endIf
endIf
if"dilbert".isOneOf("dogbert","dilbert","wally")
emit"office mate"
endIf
if"dilbert".isOneOf("ratbert","alice","asok")
emit"mate"
else
emit"coffee mate"
endIf
if"mordac".isOneOf("bob the dinosaur","garbage man","mordac")
emit"cell mate"
else
emit"don't wait"
endIf
emit"AFTER"
assertEmitted"BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER"
+ + +
 
if-2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-2
resetEmitted
iftrue
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-a1y"
elseIftrue
emit"else-a2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-b1y"
elseIftrue
emit"elseIf-b2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-y"
else
emit"else-y"
endIf
assertEmitted"if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y"
+ + +
 
if-3.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-3
resetEmitted
foreachi2, 0, 1, 4, 3, 5
ifi == 0
emit"if-${i}"
elseIfi == 1
emit"elseIf-${i}"
elseIfi == 2
emit"elseIf-${i}"
elseIfi == 3
emit"elseIf-${i}"
else
emit"else-${i}"
endIf
endForeach
assertEmitted"elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5"
+ + +
 
try - noop.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - noop
log"-- no-op try --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-noop
emit"trying"
endTryt-noop
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + +
 
try - finally with no error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - finally with no error
log"-- try/finally, w/no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-fin
emit"trying"
finally
emit"finally"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~finally~/])"
+ + +
 
try - catch but no error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch but no error
log"-- try/catch, but no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc0
emit"trying"
catch
assertEval"should NEVER enter this catch block due to no error"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + +
 
try - catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error
log"-- catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc1
throw"blamo catch ALL"
assertEval"this command should not be reached, due to thrown"
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~caught 'blamo catch ALL'~/])"
+ + +
 
try - catch specific error then finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error then finally
log"-- catch specific error, then finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel-1
emit"([/"
tryt-spec-inner
emit"trying inner"
throw"blamo inner"
assertEval"this command should not be reached, due to throw"
catch/blamo inner/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-spec-inner
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
endTryt-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])"
+ + +
 
try - catch throw finally throw.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch throw finally throw
log"-- catch/throw, finally/throw --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytcf-trap
assertEvalselblocks.tcf.nestingLevel0
trytcf
emit"trying"
emit"throwing A"
throw"blamoA"
assertEval"this command should not be reached, due to thrown"
catch/blamoA/
emit"caught '" + _error.message + "'"
emit"throwing B"
throw"blamoB"
finally
emit"finally"
emit"throwing C"
throw"blamoC"
endTry
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])"
+ + +
 
try - bubble up to catch ALL.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL
log"-- bubble up to catch ALL --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-all-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-all-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
endTryt-all-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-all-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])"
+ + +
 
try - bubble up to catch ALL via finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL via finally
log"-- bubble up to catch ALL via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-allfin-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-allfin-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-allfin-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-allfin-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])"
+ + +
 
try - bubble up out of noop try to catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up out of noop try to catch specific error
log"-- bubble out of no-op try to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trynoop-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryop-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
endTryop-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrynoop-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])"
+ + +
 
try - bubble up to catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error
log"-- bubble up to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])"
+ + +
 
try - bubble up to catch specific error via finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error via finally
log"-- bubble up to catch specific error via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])"
+ + +
 
try - throw catch rethrow.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - throw catch rethrow
log"-- throw, catch, rethrow --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryouter
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryinner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing blamo1"
throw"blamo1"
assertEval"this command should not be reached, due to throw"
catch/blamo1/
emit"caught '" + _error.message + "'"
emit"throwing blamo2"
throw"blamo2"
endTryinner
catch/blamo2/
emit"caught '" + _error.message + "'"
endTryouter
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])"
+ + +
 
try - bubble out of nested function calls.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble out of nested function calls
log"-- bubble out of nested function calls --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-invoke
emit"trying"
emit"calling"
callsubBubn = 0
assertEval"this command should not be reached, due error thrown in function"
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-invoke
assertEvalselblocks.tcf.nestingLevel-1
functionsubBubn
trytcf-inner
emit"${n}) trying-inner"
ifn < 2
emit"${n}) calling"
callsubBubn = n+1
else
emit"${n}) throwing"
throw"blamo"
endIf
finally
emit"${n}) finally"
endTrytcf-inner
assertEvalselblocks.tcf.nestingLevel0
endFunction
emit"/])"
assertEmitted"([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])"
+ + +
 
try - command bubbling break with finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling, break with finally
log"-- command bubbling, break w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"${w}) trying"
ifw==2
emit"${w}) BREAK"
break
endIf
finally
emit"${w}) finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])"
+ + +
 
try - command bubbling intra try break.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try break
log"-- command bubbling, intra-try break --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) BREAK"
break
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) BREAK~finallying~/])"
+ + +
 
try - command bubbling continue with finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling continue with finally
log"-- command bubbling, continue w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"${w}) trying"
ifw==2
emit"${w}) CONTINUE"
continue
endIf
finally
emit"${w}) finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])"
+ + +
 
try - command bubbling intra try continue.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try continue
log"-- command bubbling, intra-try continue --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) CONTINUE"
continue
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])"
+ + +
 
try - command bubbling error replaced by return.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubA
emit"returned ${_result}"
functioncmdBubA
emit"in cmdBubA"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to return/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])"
+ + +
 
try - command bubbling error replaced by return 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return 2
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubB
emit"returned ${_result}"
functioncmdBubB
emit"in cmdBubB"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"throwing"
throw"short-lived error"
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to throw/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])"
+ + +
 
try - command bubbling return replaced by error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling return replaced by error
log"-- command bubbling, return replaced by error --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubC
emit"returned ${_result}"
functioncmdBubC
emit"in cmdBubC"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf-guardrail
assertEvalselblocks.tcf.nestingLevel0
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"throwing"
throw"this-error-replaces-return-1"
endTry
catch/this-error-replaces-return-1/
emit"caught '" + _error.message + "'"
assertEvalselblocks.tcf.nestingLevel0
endTry
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])"
+ + +
 
try - exitTest with finally processing.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - exitTest with finally processing
log"-- exitTest w/finally processing --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryabort
emit"trying"
emit"exitTest ..."
exitTest
finally
emit"finallying"
assertEmitted"([/~trying~exitTest ...~finallying"
resetEmitted
endTryabort
assertEval"this command should not be reached, due to exitTest above"
+ + +
 
try - try without matching catch.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - try without matching catch
log"-- try without matching catch --"
resetEmitted
assertEvalselblocks.tcf.nestingLevel-1
trymiss
assertEvaltruetrue
throw"blamo will NOT be caught at all"
assertEval"this command should not be reached"
catch/will NOT catch it/
log"caught miss '" + _error.message + "'"
finally
log"finally"
endTrymissCommand execution failure. Please search the user group at https://groups.google.com/forum/#!forum/selenium-users for error details from the log window.  The error message is: blamo will NOT be caught at all
assertEvalselblocks.tcf.nestingLevel-1
emit"trying"
+ + +
 
while.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsw
store3w
emit"START: ${w}"
whilew == 42
emit"SHOULD NEVER HAPPEN"
endWhile
whilew > 0
emit"iter=${w}"
storeEval${w}-1w
endWhile
emit"END: ${w}"
assertEmitted"START: 3~iter=3~iter=2~iter=1~END: 3"
+ + +
 
for.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsf
emit"START ${f}"
fors=0,f=3; f <= 5; f++
emit"iter=${f}.${s}"
endFor
emit"END ${f}"
assertEmitted"START $" + "{f}~iter=3.0~iter=4.0~iter=5.0~END $" + "{f}"
+ + +
 
foreach.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVars_i, fe
emit"START ${_i}-${fe}"
foreachfe"dilbert", "dogbert", "wally"
emit"${_i}) ${fe}"
endForeach
emit"END ${_i}-${fe}"
assertEmitted"START $" + "{_i}-$" + "{fe}~0) dilbert~1) dogbert~2) wally~END $" + "{_i}-$" + "{fe}"
+ + +
 
foreach-xpath.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreachX
resetEmitted
echo$x("//input")$x("//input")
echo$X("//input")$X("//input")
echobeginbegin
emit"START ${_i}) ${link}"
foreachlink$X("//input")
emit"${_i}) ${link}"
echo${link}[object HTMLInputElement]
endForeach
emit"END ${_i}) ${link}"
assertEmitted"START ${" + "_i}) ${" + "link}~0) [object HTMLInputElement]~1) [object HTMLInputElement]~2) [object HTMLInputElement]~END ${" + "_i}) ${" + "link}"
+ + +
 
forjson.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
ifglobalContext.onServer === true
store../data/forjson.jsonforJsonFileName
else
storedata/forjson.jsonforJsonFileName
endIf
resetEmitted
deleteVarsjname
emit"START ${jname}"
forJson${forJsonFileName}
emitjname
endForJson
emit"INTERMISSION ${jname}"
loadJsonVars${forJsonFileName}jname == "dogbert"
emit"END ${jname}"
assertEmitted"START $" + "{jname}~dilbert~dogbert~wally~INTERMISSION $" + "{jname}~END dogbert"
expectError"Requires a JSON file path or URL"
loadJsonVars
expectError"Multiple JSON objects are not valid for this command"
loadJsonVars${forJsonFileName}
expectError'"flubber" is not a boolean expression'
loadJsonVars${forJsonFileName}"flubber"
+ + +
 
forxml.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
resetEmitted
deleteVarsxname
emit"START ${xname}"
forXml${forXmlFileName}
emitxname
endForXml
emit"INTERMISSION ${xname}"
loadXmlVars${forXmlFileName}xname == "dogbert"
emit"END ${xname}"
assertEmitted"START $" + "{xname}~dilbert~dogbert~wally~INTERMISSION $" + "{xname}~END dogbert"
loadXmlVars${forXmlFileName}xname == "dogbert"
expectError"Requires an XML file path or URL"
loadXmlVars
expectError"Multiple XML elements are not valid for this command"
loadXmlVars${forXmlFileName}
expectError'"flubber" is not a boolean expression'
loadXmlVars${forXmlFileName}"flubber"
+ + +
 
continue-break 1.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 1
resetEmitted
deleteVarsf
forf=3; f <= 9; f++
continuef == 6
iff > 6
iff == 7
continue
else
break
endIf
endIf
emit"iter=${f}"
endFor
assertEmitted"iter=3~iter=4~iter=5"
+ + +
 
continue-break 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 2
resetEmitted
store0i
whilei++ < 10
continuei==3
breaki==5
emit"iter=${i}"
endWhile
assertEmitted"iter=1~iter=2~iter=4"
+ + +
 
continue-break 3.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 3
resetEmitted
foreachfe"dilbert","dogbert","wally"
continuefe=="dogbert"
breakfe=="wally"
emit"iter=${fe}"
endForeach
assertEmitted"iter=dilbert"
+ + +
 
continue-break 4.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 4
resetEmitted
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
forXml${forXmlFileName}
continuexname=="dogbert"
breakxname=="wally"
emit"iter=${xname}"
endForXml
assertEmitted"iter=dilbert"
+ + +
 
nested-loops.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsi, n, uname
startTimer
store2i
emit"START ${i}"
whilei > 0
emit"while=${i}"
foreachuname"dilbert", "dogbert"
emit"foreach=${uname}"
forn = 2; n <=3; n++
emit"FOR=${n}"
forn = 7; n <= 8; n++
emit"for=${n}"
endFor
endFor
emit"endFor ${n}"
endForeach
storeEval${i}-1i
endWhile
emit"END ${i}"
timerElapsed
assertEmitted"START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2"
+ + +
 
function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
subtest
deleteVarssname, srole
assertEval"START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}"true
calldoSomethingsname = "dilbert,Q", srole = "goof"
assertEval"${_result}" === "sname=dilbert,Q,srole=goof"true
deleteVarssname, srole
functiondoSomethingsname
return"sname=${sname},srole=${srole}"
endFunctiondoSomething
deleteVarssname, srole
calldoSomethingsname = "dogbert", srole = "woof"
assertEval"${_result}" === "sname=dogbert,srole=woof"true
deleteVarssname, srole
calldoSomethingsname = "ratbert", srole = "squeak"
assertEval"${_result}" === "sname=ratbert,srole=squeak"true
deleteVarssname, srole
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
assertEval"${_result}" === "sname=${sname},srole=super=user"true
deleteVarssname, srole
endForeach
assertEval"DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}"true
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
deleteVarssname, srole
scriptdoDeprecatedsname
return"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEval"${_result}" === "sname=wally,srole=lazy"true
deleteVarssname, srole
+ + +
 
function-recursive.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
factorial
resetEmitted
deleteVarsdegree, n, _result, ud
store7degree
startTimerfactorial ${degree}
callfacn=degree
timerElapsed
emitdegree + "!=" + _result
functionfacn
ifn <= 1
return1
else
callfacn = n-1
emit_result
returnn * _result
endIf
endFunction
functionuno
emit"UNO"
storeEval${ud}-1ud
ifud > 0
calldue
endIf
endFunctionuno
functiondue
emit"DUE"
storeEval${ud}-1ud
ifud > 0
calluno
endIf
endFunctiondue
store5ud
calluno
assertEmitted"1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO"
+ + +
 
issue-2-function.html
+ + + + + + + + + + + + + + + + + + + + + + + + +
issue#2
functionxyz
log'here'
endFunction
callxyz
+ + +
 
exitTest - base case.html
+ + + + + + + + + + + + + + + + + + + + +
exitTest - base case
resetEmitted
exitTest
throw"shouldn't happen"
+ + +
 
exitTest - from within a loop.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a loop
fori=0; i < 5; i++
ifi == 3
exitTest
endIf
ifi === 3
throw"This test should exit when the increment gets to 3, and this should never be thrown."
endIf
endFor
+ + +
 
exitTest - from within a function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a function
calldoSubExit
throw"shouldn't happen"
functiondoSubExit
exitTest
endFunctiondoSubExit
+ + +
 
GlobalFunctions.html
+ + + + + + + + + + + + + + + + + + + + + + + + +
functions
getEvalglobalStoredVars = {};
functionsetGlobalVar
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
+ + +
 
CallGlobalFunction.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + +
 
DefineFunctionParameters - Base.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - Base
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionbobx,y
assertEval"${x}" === "overwritten"true
assertEvalstoredVars.y === undefinedtrue
endFunction
callbobx="overwritten"
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEvalstoredVars.y === undefinedfalse
assertEval"${y}" === "original";true
+ + +
 
DefineFunctionParameters - With Default Values.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - With Default Values
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionleakTestx="fn default x",y="fn default y"
storeoverwrittenx
storeoverwritteny
endFunction
functiondefaultsTestx="fn default x",y="fn default y"
assertEval${x} === "fn default x"true
store"overwritten"x
assertEval${x} === "overwritten"true
assertEval${y} === "fn default y"true
store"overwritten"y
assertEval${y} === "overwritten"true
endFunction
calldefaultsTest
callleakTest
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTesty = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten", y = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
+ + +
 
StoreLocal - Function Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
StoreGlobal - Function Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - Function Scope
functionblockScopeVars
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endFunction
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + +
 
StoreGlobal - While Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - While Scope
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
store1i
whilei > 0
store0i
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endWhile
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + +
 
StoreLocal - While Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - While Scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
store1i
whilei > 0
store0i
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endWhile
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
Store - Behaves as StoreLocal.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store - Behaves as StoreLocal
functionblockScopeVars
storethis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
Function - Can Return Value.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Function - Can Return Value
functionreturnsValue
return"banana"
endFunction
callreturnsValue
assertEval"${_result}" === "banana"true
+ + +
 
StoreAt - Function Scope Nesting.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - Function Scope Nesting
functionstorel
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
endFunction
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
callstorel
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + +
 
StoreAt - While Scope Nesting.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - While Scope Nesting
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
storeLocal3x
whilex !== 0
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
storeEvalLocalx -= 1
endWhile
deleteVarx
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + +
 
sendkeys keys are preserved.html
+ + + + + + + + + + + + + + + + + + + + +
sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ + +
 
+info: Starting test /selenium-server/tests/README.html
+info: Executing: |open | http://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.html |  |
+info: Starting test /selenium-server/tests/eval.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "dilbert".isOneOf("dilbert","dogbert","mordac") |  |
+info: Executing: |emit | "bob".isOneOf("dilbert","dogbert","mordac") |  |
+info: Executing: |emit | "red".mapTo("primary", ["red","green","blue"]) |  |
+info: Executing: |emit | "orange".mapTo("primary", ["red","green","blue"]) |  |
+info: Executing: |emit | "red".translate("e", "E") |  |
+info: Executing: |emit | "red".translate(["red", "green", "blue"], ["blue", "red", "green"]) |  |
+info: Executing: |assertEmitted | "true~false~primary~orange~rEd~blue" |  |
+info: Starting test /selenium-server/tests/branching.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "BEFORE" |  |
+info: Executing: |goto | HERE |  |
+info: [SelBlocks] branch => @5: [label|HERE]
+info: Executing: |label | HERE |  |
+info: Executing: |gotoIf | true | THERE |
+info: [SelBlocks] branch => @8: [label|THERE]
+info: Executing: |label | THERE |  |
+info: Executing: |skipNext |  |  |
+info: [SelBlocks] branch => @11: [emit|"AFTER"]
+info: Executing: |emit | "AFTER" |  |
+info: Executing: |assertEmitted | "BEFORE~AFTER" |  |
+info: Executing: |expectError | "Target label 'NOWHERE' is not found" |  |
+info: Executing: |goto | NOWHERE |  |
+error: [SelBlocks] Error @14: [goto|NOWHERE] Target label 'NOWHERE' is not found.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Target label 'NOWHERE' is not found" |  |
+info: Executing: |gotoIf | true | NOWHERE |
+error: [SelBlocks] Error @16: [gotoIf|true|NOWHERE] Target label 'NOWHERE' is not found.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Requires a number > 1" |  |
+info: Executing: |skipNext | -1 |  |
+error: [SelBlocks] Error @18: [skipNext|-1] Requires a number > 1
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | /.*random.* (is not |is un)defined/ |  |
+info: Executing: |skipNext | random |  |
+error: [SelBlocks] Error  While evaluating Javascript expression: random
+warn: [SelBlocks] __Stack Trace__
+info: Starting test /selenium-server/tests/if-1.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "BEFORE" |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "truthy" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @8: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "A" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @16: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "Y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @21: [else]
+info: Executing: |else |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "truthF" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @26: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "dilbert".isOneOf("dogbert","dilbert","wally") |  |
+info: Executing: |emit | "office mate" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "dilbert".isOneOf("ratbert","alice","asok") |  |
+info: [SelBlocks] branch => @33: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "coffee mate" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "mordac".isOneOf("bob the dinosaur","garbage man","mordac") |  |
+info: Executing: |emit | "cell mate" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @40: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "AFTER" |  |
+info: Executing: |assertEmitted | "BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER" |  |
+info: Starting test /selenium-server/tests/if-2.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "if-y" |  |
+info: Executing: |elseIf | true |  |
+info: [SelBlocks] branch => @6: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @9: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @14: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-a1y" |  |
+info: Executing: |elseIf | true |  |
+info: [SelBlocks] branch => @18: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @21: [elseIf|false]
+info: Executing: |elseIf | false |  |
+info: [SelBlocks] branch => @23: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-b2y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @28: [elseIf|false]
+info: Executing: |elseIf | false |  |
+info: [SelBlocks] branch => @30: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |assertEmitted | "if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y" |  |
+info: Starting test /selenium-server/tests/if-3.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: Executing: |emit | "if-${i}" |  |
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-${i}" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-${i}" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: [SelBlocks] branch => @14: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEmitted | "elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5" |  |
+info: Starting test /selenium-server/tests/try%20-%20noop.html
+info: Executing: |log | "-- no-op try --" |  |
+info: [SelBench] -- no-op try --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-noop |  |
+warn: [SelBlocks] @5: [try|t-noop] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying" |  |
+info: Executing: |endTry | t-noop |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20finally%20with%20no%20error.html
+info: Executing: |log | "-- try/finally, w/no error --" |  |
+info: [SelBench] -- try/finally, w/no error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-fin |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20but%20no%20error.html
+info: Executing: |log | "-- try/catch, but no error --" |  |
+info: [SelBench] -- try/catch, but no error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tc0 |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |catch |  |  |
+info: [SelBlocks] branch => @9: [endTry]
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20specific%20error.html
+info: Executing: |log | "-- catch specific error --" |  |
+info: [SelBench] -- catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tc1 |  |
+info: Executing: |throw | "blamo catch ALL" |  |
+info: [SelBlocks] @6, error has been caught :: 
+info: [SelBlocks] branch => @8: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~caught 'blamo catch ALL'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20specific%20error%20then%20finally.html
+info: Executing: |log | "-- catch specific error, then finally --" |  |
+info: [SelBench] -- catch specific error, then finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-spec-outer |  |
+warn: [SelBlocks] @5: [try|t-spec-outer] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "([/" |  |
+info: Executing: |try | t-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |throw | "blamo inner" |  |
+info: [SelBlocks] @11, error has been caught :: /blamo inner/
+info: [SelBlocks] branch => @13: [catch|/blamo inner/]
+info: Executing: |catch | /blamo inner/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | t-spec-inner |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |endTry | t-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20throw%20finally%20throw.html
+info: Executing: |log | "-- catch/throw, finally/throw --" |  |
+info: [SelBench] -- catch/throw, finally/throw --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tcf-trap |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "throwing A" |  |
+info: Executing: |throw | "blamoA" |  |
+info: [SelBlocks] @10, error has been caught :: /blamoA/
+info: [SelBlocks] branch => @12: [catch|/blamoA/]
+info: Executing: |catch | /blamoA/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |emit | "throwing B" |  |
+info: Executing: |throw | "blamoB" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @16: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |emit | "throwing C" |  |
+info: Executing: |throw | "blamoC" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @20: [endTry]
+info: Executing: |endTry |  |  |
+info: [SelBlocks] @20, error has been caught :: @19 
+info: [SelBlocks] branch => @22: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20ALL.html
+info: Executing: |log | "-- bubble up to catch ALL --" |  |
+info: [SelBench] -- bubble up to catch ALL --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-all-outer |  |
+info: Executing: |emit | "trying-outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-all-inner |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |throw | "blamo try-catch-finally" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @14: [endTry|t-all-inner]
+info: Executing: |endTry | t-all-inner |  |
+info: [SelBlocks] @14, error has been caught :: @10 
+info: [SelBlocks] branch => @16: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught-outer '" + _error.message + "'" |  |
+info: Executing: |endTry | t-all-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20ALL%20via%20finally.html
+info: Executing: |log | "-- bubble up to catch ALL via finally --" |  |
+info: [SelBench] -- bubble up to catch ALL via finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-allfin-outer |  |
+info: Executing: |emit | "trying-outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-allfin-inner |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |throw | "blamo try-catch-finally" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | t-allfin-inner |  |
+info: [SelBlocks] @16, error has been caught :: @10 
+info: [SelBlocks] branch => @18: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught-outer '" + _error.message + "'" |  |
+info: Executing: |endTry | t-allfin-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20out%20of%20noop%20try%20to%20catch%20specific%20error.html
+info: Executing: |log | "-- bubble out of no-op try to catch specific error --" |  |
+info: [SelBench] -- bubble out of no-op try to catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | noop-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | op-inner |  |
+warn: [SelBlocks] @8: [try|op-inner] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @14: [endTry|op-inner]
+info: Executing: |endTry | op-inner |  |
+info: [SelBlocks] @14, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @15: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | noop-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20specific%20error.html
+info: Executing: |log | "-- bubble up to catch specific error --" |  |
+info: [SelBench] -- bubble up to catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-inner |  |
+info: [SelBlocks] @16, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @17: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry | bub-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20specific%20error%20via%20finally.html
+info: Executing: |log | "-- bubble up to catch specific error via finally --" |  |
+info: [SelBench] -- bubble up to catch specific error via finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-inner |  |
+info: [SelBlocks] @16, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @17: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20throw%20catch%20rethrow.html
+info: Executing: |log | "-- throw, catch, rethrow --" |  |
+info: [SelBench] -- throw, catch, rethrow --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing blamo1" |  |
+info: Executing: |throw | "blamo1" |  |
+info: [SelBlocks] @12, error has been caught :: /blamo1/
+info: [SelBlocks] branch => @14: [catch|/blamo1/]
+info: Executing: |catch | /blamo1/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |emit | "throwing blamo2" |  |
+info: Executing: |throw | "blamo2" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @18: [endTry|inner]
+info: Executing: |endTry | inner |  |
+info: [SelBlocks] @18, error has been caught :: @17 /blamo2/
+info: [SelBlocks] branch => @19: [catch|/blamo2/]
+info: Executing: |catch | /blamo2/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry | outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20out%20of%20nested%20function%20calls.html
+info: Executing: |log | "-- bubble out of nested function calls --" |  |
+info: [SelBench] -- bubble out of nested function calls --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-invoke |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | subBub | n = 0 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: Executing: |emit | "${n}) calling" |  |
+info: Executing: |call | subBub | n = n+1 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: Executing: |emit | "${n}) calling" |  |
+info: Executing: |call | subBub | n = n+1 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: [SelBlocks] branch => @22: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "${n}) throwing" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] @28, error has been caught :: @28 /blamo/
+info: [SelBlocks] branch => @10: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-invoke |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |function | subBub | n |
+info: [SelBlocks] branch => @30: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20break%20with%20finally.html
+info: Executing: |log | "-- command bubbling, break w/finally --" |  |
+info: [SelBench] -- command bubbling, break w/finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) BREAK" |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] Command @11: [break], suspended while finally block runs
+info: [SelBlocks] branch => @13: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @11: [break]
+info: [SelBlocks] branch => @11: [break]
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @18: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20intra%20try%20break.html
+info: Executing: |log | "-- command bubbling, intra-try break --" |  |
+info: [SelBench] -- command bubbling, intra-try break --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) BREAK" |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~while'g~3) iterating~2) BREAK~finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20continue%20with%20finally.html
+info: Executing: |log | "-- command bubbling, continue w/finally --" |  |
+info: [SelBench] -- command bubbling, continue w/finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) CONTINUE" |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] Command @11: [continue], suspended while finally block runs
+info: [SelBlocks] branch => @13: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @11: [continue]
+info: [SelBlocks] branch => @11: [continue]
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: [SelBlocks] branch => @18: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20intra%20try%20continue.html
+info: Executing: |log | "-- command bubbling, intra-try continue --" |  |
+info: [SelBench] -- command bubbling, intra-try continue --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) CONTINUE" |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20error%20replaced%20by%20return.html
+info: Executing: |log | "-- command bubbling, error replaced by return --" |  |
+info: [SelBench] -- command bubbling, error replaced by return --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubA |  |
+info: [SelBlocks] branch => @7: [function|cmdBubA]
+info: Executing: |function | cmdBubA |  |
+info: Executing: |emit | "in cmdBubA" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "returning (1)" |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] Command @13: [return|1], suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "returning (2)" |  |
+info: Executing: |return | 2 |  |
+info: Executing: |endTry |  |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @17: [return|2]
+info: [SelBlocks] branch => @17: [return|2]
+info: Executing: |return | 2 |  |
+info: [SelBlocks] branch => @5: [call|cmdBubA]
+info: Executing: |call | cmdBubA |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubA |  |
+info: [SelBlocks] branch => @20: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20error%20replaced%20by%20return%202.html
+info: Executing: |log | "-- command bubbling, error replaced by return --" |  |
+info: [SelBench] -- command bubbling, error replaced by return --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubB |  |
+info: [SelBlocks] branch => @7: [function|cmdBubB]
+info: Executing: |function | cmdBubB |  |
+info: Executing: |emit | "in cmdBubB" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "throwing" |  |
+info: Executing: |throw | "short-lived error" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "returning (2)" |  |
+info: Executing: |return | 2 |  |
+info: Executing: |endTry |  |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @17: [return|2]
+info: [SelBlocks] branch => @17: [return|2]
+info: Executing: |return | 2 |  |
+info: [SelBlocks] branch => @5: [call|cmdBubB]
+info: Executing: |call | cmdBubB |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubB |  |
+info: [SelBlocks] branch => @20: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20return%20replaced%20by%20error.html
+info: Executing: |log | "-- command bubbling, return replaced by error --" |  |
+info: [SelBench] -- command bubbling, return replaced by error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubC |  |
+info: [SelBlocks] branch => @7: [function|cmdBubC]
+info: Executing: |function | cmdBubC |  |
+info: Executing: |emit | "in cmdBubC" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf-guardrail |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "returning (1)" |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] Command @15: [return|1], suspended while finally block runs
+info: [SelBlocks] branch => @16: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "throwing" |  |
+info: Executing: |throw | "this-error-replaces-return-1" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @20: [endTry]
+info: Executing: |endTry |  |  |
+info: [SelBlocks] @20, error has been caught :: @19 /this-error-replaces-return-1/
+info: [SelBlocks] branch => @21: [catch|/this-error-replaces-return-1/]
+info: Executing: |catch | /this-error-replaces-return-1/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |endTry |  |  |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @5: [call|cmdBubC]
+info: Executing: |call | cmdBubC |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubC |  |
+info: [SelBlocks] branch => @25: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20exitTest%20with%20finally%20processing.html
+info: Executing: |log | "-- exitTest w/finally processing --" |  |
+info: [SelBench] -- exitTest w/finally processing --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | abort |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "exitTest ..." |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] Command @8: [exitTest], suspended while finally block runs
+info: [SelBlocks] branch => @9: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |assertEmitted | "([/~trying~exitTest ...~finallying" |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |endTry | abort |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @8: [exitTest]
+info: [SelBlocks] branch => @8: [exitTest]
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/try%20-%20try%20without%20matching%20catch.html
+info: Executing: |log | "-- try without matching catch --" |  |
+info: [SelBench] -- try without matching catch --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | miss |  |
+info: Executing: |assertEval | true | true |
+info: script is: true
+info: Executing: |throw | "blamo will NOT be caught at all" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @10: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |log | "finally" |  |
+info: [SelBench] finally
+info: Executing: |endTry | miss |  |
+error: [SelBlocks] Error was not caught: 'blamo will NOT be caught at all'
+error: Unexpected Exception: blamo will NOT be caught at all
+error: Exception details: name -> SelblocksError, message -> blamo will NOT be caught at all, idx -> 5
+warn: currentTest.recordFailure: Command execution failure. Please search the user group at https://groups.google.com/forum/#!forum/selenium-users for error details from the log window.  The error message is: blamo will NOT be caught at all
+info: Starting test /selenium-server/tests/while.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | w |  |
+info: Executing: |store | 3 | w |
+info: Executing: |emit | "START: ${w}" |  |
+info: Executing: |while | w == 42 |  |
+info: [SelBlocks] branch => @7: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 3-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 2-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 1-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: [SelBlocks] branch => @11: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |emit | "END: ${w}" |  |
+info: Executing: |assertEmitted | "START: 3~iter=3~iter=2~iter=1~END: 3" |  |
+info: Starting test /selenium-server/tests/for.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | f |  |
+info: Executing: |emit | "START ${f}" |  |
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: [SelBlocks] branch => @6: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "END ${f}" |  |
+info: Executing: |assertEmitted | "START $" + "{f}~iter=3.0~iter=4.0~iter=5.0~END $" + "{f}" |  |
+info: Starting test /selenium-server/tests/foreach.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | _i, fe |  |
+info: Executing: |emit | "START ${_i}-${fe}" |  |
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: [SelBlocks] branch => @6: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "END ${_i}-${fe}" |  |
+info: Executing: |assertEmitted | "START $" + "{_i}-$" + "{fe}~0) dilbert~1) dogbert~2) wally~END $" + "{_i}-$" + "{fe}" |  |
+info: Starting test /selenium-server/tests/foreach-xpath.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |echo | $x("//input") |  |
+info: Executing: |echo | $X("//input") |  |
+info: Executing: |echo | begin |  |
+info: Executing: |emit | "START ${_i}) ${link}" |  |
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} | [object HTMLInputElement] |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} | [object HTMLInputElement] |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: [SelBlocks] branch => @9: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "END ${_i}) ${link}" |  |
+info: Executing: |assertEmitted | "START ${" + "_i}) ${" + "link}~0) [object HTMLInputElement]~1) [object HTMLInputElement]~2) [object HTMLInputElement]~END ${" + "_i}) ${" + "link}" |  |
+info: Starting test /selenium-server/tests/forjson.html
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forjson.json | forJsonFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @5: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | jname |  |
+info: Executing: |emit | "START ${jname}" |  |
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: [SelBlocks] Reading from: ../data/forjson.json
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: [SelBlocks] branch => @11: [endForJson]
+info: Executing: |endForJson |  |  |
+info: Executing: |emit | "INTERMISSION ${jname}" |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} | jname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forjson.json
+info: Executing: |emit | "END ${jname}" |  |
+info: Executing: |assertEmitted | "START $" + "{jname}~dilbert~dogbert~wally~INTERMISSION $" + "{jname}~END dogbert" |  |
+info: Executing: |expectError | "Requires a JSON file path or URL" |  |
+info: Executing: |loadJsonVars |  |  |
+error: [SelBlocks] Error @17: [loadJsonVars] Requires a JSON file path or URL.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Multiple JSON objects are not valid for this command" |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} |  |
+info: [SelBlocks] Reading from: ../data/forjson.json
+error: [SelBlocks] Error @19: [loadJsonVars|${forJsonFileName}] Multiple JSON objects are not valid for this command. (A specific JSON object can be selected by specifying: name="value".)
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | '"flubber" is not a boolean expression' |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} | "flubber" |
+info: [SelBlocks] Reading from: ../data/forjson.json
+error: [SelBlocks] Error @21: [loadJsonVars|${forJsonFileName}|"flubber"], "flubber" is not a boolean expression
+warn: [SelBlocks] __Stack Trace__
+info: Starting test /selenium-server/tests/forxml.html
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forxml.xml | forXmlFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @5: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | xname |  |
+info: Executing: |emit | "START ${xname}" |  |
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] branch => @11: [endForXml]
+info: Executing: |endForXml |  |  |
+info: Executing: |emit | "INTERMISSION ${xname}" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | xname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |emit | "END ${xname}" |  |
+info: Executing: |assertEmitted | "START $" + "{xname}~dilbert~dogbert~wally~INTERMISSION $" + "{xname}~END dogbert" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | xname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |expectError | "Requires an XML file path or URL" |  |
+info: Executing: |loadXmlVars |  |  |
+error: [SelBlocks] Error @18: [loadXmlVars] Requires an XML file path or URL.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Multiple XML elements are not valid for this command" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+error: [SelBlocks] Error @20: [loadXmlVars|${forXmlFileName}] Multiple XML elements are not valid for this command. (A specific XML element can be selected by specifying: name="value".)
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | '"flubber" is not a boolean expression' |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | "flubber" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+error: [SelBlocks] Error @22: [loadXmlVars|${forXmlFileName}|"flubber"], "flubber" is not a boolean expression
+warn: [SelBlocks] __Stack Trace__
+info: Starting test /selenium-server/tests/continue-break%201.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | f |  |
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: Executing: |if | f == 7 |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: Executing: |if | f == 7 |  |
+info: [SelBlocks] branch => @8: [else]
+info: Executing: |else |  |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @13: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |assertEmitted | "iter=3~iter=4~iter=5" |  |
+info: Starting test /selenium-server/tests/continue-break%202.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |store | 0 | i |
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: [SelBlocks] branch => @7: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEmitted | "iter=1~iter=2~iter=4" |  |
+info: Starting test /selenium-server/tests/continue-break%203.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: Executing: |break | fe=="wally" |  |
+info: Executing: |emit | "iter=${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|fe|"dilbert","dogbert","wally"]
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: [SelBlocks] branch => @2: [foreach|fe|"dilbert","dogbert","wally"]
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: Executing: |break | fe=="wally" |  |
+info: [SelBlocks] branch => @6: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEmitted | "iter=dilbert" |  |
+info: Starting test /selenium-server/tests/continue-break%204.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forxml.xml | forXmlFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @6: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |continue | xname=="dogbert" |  |
+info: Executing: |break | xname=="wally" |  |
+info: Executing: |emit | "iter=${xname}" |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @7: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |continue | xname=="dogbert" |  |
+info: [SelBlocks] branch => @7: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |continue | xname=="dogbert" |  |
+info: Executing: |break | xname=="wally" |  |
+info: [SelBlocks] branch => @11: [endForXml]
+info: Executing: |endForXml |  |  |
+info: Executing: |assertEmitted | "iter=dilbert" |  |
+info: Starting test /selenium-server/tests/nested-loops.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | i, n, uname |  |
+info: Executing: |startTimer |  |  |
+info: Executing: |store | 2 | i |
+info: Executing: |emit | "START ${i}" |  |
+info: Executing: |while | i > 0 |  |
+info: Executing: |emit | "while=${i}" |  |
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: [SelBlocks] branch => @17: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |storeEval | ${i}-1 | i |
+info: script is: 2-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: Executing: |emit | "while=${i}" |  |
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: [SelBlocks] branch => @17: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |storeEval | ${i}-1 | i |
+info: script is: 1-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @19: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |emit | "END ${i}" |  |
+info: Executing: |timerElapsed |  |  |
+info: [SelBench] 2.276 sec elapsed: 
+info: Executing: |assertEmitted | "START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2" |  |
+info: Starting test /selenium-server/tests/function.html
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |assertEval | "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}" | true |
+info: script is: "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}"
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @3: [call|doSomething|sname = "dilbert,Q", srole = "goof"]
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: Executing: |assertEval | "${_result}" === "sname=dilbert,Q,srole=goof" | true |
+info: script is: "sname=dilbert,Q,srole=goof" === "sname=dilbert,Q,srole=goof"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |function | doSomething | sname |
+info: [SelBlocks] branch => @8: [endFunction|doSomething]
+info: Executing: |endFunction | doSomething |  |
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @10: [call|doSomething|sname = "dogbert", srole = "woof"]
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: Executing: |assertEval | "${_result}" === "sname=dogbert,srole=woof" | true |
+info: script is: "sname=dogbert,srole=woof" === "sname=dogbert,srole=woof"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @13: [call|doSomething|sname = "ratbert", srole = "squeak"]
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: Executing: |assertEval | "${_result}" === "sname=ratbert,srole=squeak" | true |
+info: script is: "sname=ratbert,srole=squeak" === "sname=ratbert,srole=squeak"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @17: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |assertEval | "${_result}" === "sname=${sname},srole=super=user" | true |
+info: script is: "sname=asok,srole=super=user" === "sname=asok,srole=super=user"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @17: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |assertEval | "${_result}" === "sname=${sname},srole=super=user" | true |
+info: script is: "sname=alice,srole=super=user" === "sname=alice,srole=super=user"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: [SelBlocks] branch => @20: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEval | "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}" | true |
+info: script is: "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}"
+info: Executing: |expectError | "Function does not exist: NONEXISTENT" |  |
+info: Executing: |call | NONEXISTENT |  |
+error: [SelBlocks] Error @23: [call|NONEXISTENT] Function does not exist: NONEXISTENT
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |script | doDeprecated | sname |
+warn: [SelBlocks] The script command has been deprecated and will be removed in future releases. Please use function instead.
+info: [SelBlocks] branch => @27: [endScript|doDeprecated]
+info: Executing: |endScript | doDeprecated |  |
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: [SelBlocks] branch => @25: [script|doDeprecated|sname]
+info: Executing: |script | doDeprecated | sname |
+warn: [SelBlocks] The script command has been deprecated and will be removed in future releases. Please use function instead.
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @28: [call|doDeprecated|sname = "wally", srole = "lazy"]
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: Executing: |assertEval | "${_result}" === "sname=wally,srole=lazy" | true |
+info: script is: "sname=wally,srole=lazy" === "sname=wally,srole=lazy"
+info: Executing: |deleteVars | sname, srole |  |
+info: Starting test /selenium-server/tests/function-recursive.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | degree, n, _result, ud |  |
+info: Executing: |store | 7 | degree |
+info: Executing: |startTimer |  | factorial ${degree} |
+info: Executing: |call | fac | n=degree |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @5: [call|fac|n=degree]
+info: Executing: |call | fac | n=degree |
+info: Executing: |timerElapsed |  |  |
+info: [SelBench] 0.826 sec elapsed: factorial 7
+info: Executing: |emit | degree + "!=" + _result |  |
+info: Executing: |function | fac | n |
+info: [SelBlocks] branch => @16: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |function | uno |  |
+info: [SelBlocks] branch => @23: [endFunction|uno]
+info: Executing: |endFunction | uno |  |
+info: Executing: |function | due |  |
+info: [SelBlocks] branch => @30: [endFunction|due]
+info: Executing: |endFunction | due |  |
+info: Executing: |store | 5 | ud |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 5-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | due |  |
+info: [SelBlocks] branch => @24: [function|due]
+info: Executing: |function | due |  |
+info: Executing: |emit | "DUE" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 4-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 3-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | due |  |
+info: [SelBlocks] branch => @24: [function|due]
+info: Executing: |function | due |  |
+info: Executing: |emit | "DUE" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 2-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 1-1
+info: Executing: |if | ud > 0 |  |
+info: [SelBlocks] branch => @22: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @28: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | due |  |
+info: [SelBlocks] branch => @21: [call|due]
+info: Executing: |call | due |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @28: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | due |  |
+info: [SelBlocks] branch => @21: [call|due]
+info: Executing: |call | due |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @32: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |assertEmitted | "1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO" |  |
+info: Starting test /selenium-server/tests/issue-2-function.html
+info: Executing: |function | xyz |  |
+info: [SelBlocks] branch => @3: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | xyz |  |
+info: [SelBlocks] branch => @1: [function|xyz]
+info: Executing: |function | xyz |  |
+info: Executing: |log | 'here' |  |
+info: [SelBench] here
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @4: [call|xyz]
+info: Executing: |call | xyz |  |
+info: Starting test /selenium-server/tests/exitTest%20-%20base%20case.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/exitTest%20-%20from%20within%20a%20loop.html
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/exitTest%20-%20from%20within%20a%20function.html
+info: Executing: |call | doSubExit |  |
+info: [SelBlocks] branch => @3: [function|doSubExit]
+info: Executing: |function | doSubExit |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/GlobalFunctions.html
+info: Executing: |getEval | globalStoredVars = {}; |  |
+info: script is: globalStoredVars = {};
+info: Executing: |function | setGlobalVar |  |
+info: [SelBlocks] branch => @4: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Starting test /selenium-server/tests/CallGlobalFunction.html
+info: Executing: |getEval | globalStoredVars.aGlobalVar = "reset"; |  |
+info: script is: globalStoredVars.aGlobalVar = "reset";
+info: Executing: |assertNotEval | globalStoredVars.aGlobalVar; | set |
+info: script is: globalStoredVars.aGlobalVar;
+info: Executing: |assertEval | globalStoredVars.aGlobalVar; | reset |
+info: script is: globalStoredVars.aGlobalVar;
+info: Executing: |call | GlobalFunctions.setGlobalVar |  |
+info: [SelBlocks] branch => @2: [assertNotEval|globalStoredVars.aGlobalVar;|set]
+info: Executing: |function | setGlobalVar |  |
+info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; |  |
+info: script is: globalStoredVars.aGlobalVar = "set";
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @4: [call|GlobalFunctions.setGlobalVar]
+info: Executing: |call | GlobalFunctions.setGlobalVar |  |
+info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set |
+info: script is: globalStoredVars.aGlobalVar;
+info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20Base.html
+info: Executing: |store | original | x |
+info: Executing: |store | original | y |
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |function | bob | x,y |
+info: [SelBlocks] branch => @8: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | bob | x="overwritten" |
+info: [SelBlocks] branch => @5: [function|bob|x,y]
+info: Executing: |function | bob | x,y |
+info: Executing: |assertEval | "${x}" === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |assertEval | storedVars.y === undefined | true |
+info: script is: storedVars.y === undefined
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @9: [call|bob|x="overwritten"]
+info: Executing: |call | bob | x="overwritten" |
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | storedVars.y === undefined | false |
+info: script is: storedVars.y === undefined
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20With%20Default%20Values.html
+info: Executing: |store | original | x |
+info: Executing: |store | original | y |
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: [SelBlocks] branch => @8: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |function | defaultsTest | x="fn default x",y="fn default y" |
+info: [SelBlocks] branch => @16: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | defaultsTest |  |
+info: [SelBlocks] branch => @9: [function|defaultsTest|x="fn default x",y="fn default y"]
+info: Executing: |function | defaultsTest | x="fn default x",y="fn default y" |
+info: Executing: |assertEval | ${x} === "fn default x" | true |
+info: script is: "fn default x" === "fn default x"
+info: Executing: |store | "overwritten" | x |
+info: Executing: |assertEval | ${x} === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |assertEval | ${y} === "fn default y" | true |
+info: script is: "fn default y" === "fn default y"
+info: Executing: |store | "overwritten" | y |
+info: Executing: |assertEval | ${y} === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @17: [call|defaultsTest]
+info: Executing: |call | defaultsTest |  |
+info: Executing: |call | leakTest |  |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @18: [call|leakTest]
+info: Executing: |call | leakTest |  |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | y = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @25: [call|leakTest|y = "overwritten"]
+info: Executing: |call | leakTest | y = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | x = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @32: [call|leakTest|x = "overwritten"]
+info: Executing: |call | leakTest | x = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | x = "overwritten", y = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @39: [call|leakTest|x = "overwritten", y = "overwritten"]
+info: Executing: |call | leakTest | x = "overwritten", y = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Starting test /selenium-server/tests/StoreLocal%20-%20Function%20Scope.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |storeLocal | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @12: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/StoreGlobal%20-%20Function%20Scope.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.g = null; |  |
+info: script is: storedVarsGlobal.g = null;
+info: Executing: |assertEval | storedVarsGlobal.g === null; | true |
+info: script is: storedVarsGlobal.g === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |storeGlobal | this is stored globally | g |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @10: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Starting test /selenium-server/tests/StoreGlobal%20-%20While%20Scope.html
+info: Executing: |getEval | storedVarsGlobal.g = null; |  |
+info: script is: storedVarsGlobal.g = null;
+info: Executing: |assertEval | storedVarsGlobal.g === null; | true |
+info: script is: storedVarsGlobal.g === null;
+info: Executing: |store | 1 | i |
+info: Executing: |while | i > 0 |  |
+info: Executing: |store | 0 | i |
+info: Executing: |storeGlobal | this is stored globally | g |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @4: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @11: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Starting test /selenium-server/tests/StoreLocal%20-%20While%20Scope.html
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |store | 1 | i |
+info: Executing: |while | i > 0 |  |
+info: Executing: |store | 0 | i |
+info: Executing: |storeLocal | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @13: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/Store%20-%20Behaves%20as%20StoreLocal.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |store | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @12: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/Function%20-%20Can%20Return%20Value.html
+info: Executing: |function | returnsValue |  |
+info: [SelBlocks] branch => @3: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | returnsValue |  |
+info: [SelBlocks] branch => @1: [function|returnsValue]
+info: Executing: |function | returnsValue |  |
+info: Executing: |return | "banana" |  |
+info: [SelBlocks] branch => @4: [call|returnsValue]
+info: Executing: |call | returnsValue |  |
+info: Executing: |assertEval | "${_result}" === "banana" | true |
+info: script is: "banana" === "banana"
+info: Starting test /selenium-server/tests/StoreAt%20-%20Function%20Scope%20Nesting.html
+info: Executing: |function | storel |  |
+info: [SelBlocks] branch => @9: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.notDefined = null |  |
+info: script is: storedVarsGlobal.notDefined = null
+info: Executing: |assertEval | storedVarsGlobal.notDefined === null | true |
+info: script is: storedVarsGlobal.notDefined === null
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |storeLocal | exists in parent | l |
+info: Executing: |assertEval | storedVars.l === "exists in parent"; | true |
+info: script is: storedVars.l === "exists in parent";
+info: Executing: |call | storel |  |
+info: [SelBlocks] branch => @1: [function|storel]
+info: Executing: |function | storel |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @16: [call|storel]
+info: Executing: |call | storel |  |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Starting test /selenium-server/tests/StoreAt%20-%20While%20Scope%20Nesting.html
+info: Executing: |getEval | storedVarsGlobal.notDefined = null |  |
+info: script is: storedVarsGlobal.notDefined = null
+info: Executing: |assertEval | storedVarsGlobal.notDefined === null | true |
+info: script is: storedVarsGlobal.notDefined === null
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |storeLocal | exists in parent | l |
+info: Executing: |assertEval | storedVars.l === "exists in parent"; | true |
+info: script is: storedVars.l === "exists in parent";
+info: Executing: |storeLocal | 3 | x |
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: [SelBlocks] branch => @17: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |deleteVar | x |  |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Starting test /selenium-server/tests/sendkeys%20keys%20are%20preserved.html
+info: Executing: |assertEval | "KEY_ENTER" in storedVars | true |
+info: script is: "KEY_ENTER" in storedVars
+info: Executing: |assertEval | "KEY_TAB" in storedVars | true |
+info: script is: "KEY_TAB" in storedVars
+info: Executing: |assertEval | "KEY_BACKSPACE" in storedVars | true |
+info: script is: "KEY_BACKSPACE" in storedVars
+
\ No newline at end of file diff --git a/testUserExtension/results-googlechrome.html b/testUserExtension/results-googlechrome.html new file mode 100644 index 0000000..e1f227b --- /dev/null +++ b/testUserExtension/results-googlechrome.html @@ -0,0 +1,8084 @@ + +Test suite results + +

Test suite results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
result:failed
totalTime:15
numTestTotal:58
numTestPasses:57
numTestFailures:1
numCommandPasses:196
numCommandFailures:0
numCommandErrors:1
Selenium Version:2.43
Selenium Revision:.1
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test Suite
README
eval
branching
if-1
if-2
if-3
try - noop
try - finally with no error
try - catch but no error
try - catch specific error
try - catch specific error then finally
try - catch throw finally throw
try - bubble up to catch ALL
try - bubble up to catch ALL via finally
try - bubble up out of noop try to catch specific error
try - bubble up to catch specific error
try - bubble up to catch specific error via finally
try - throw catch rethrow
try - bubble out of nested function calls
try - command bubbling break with finally
try - command bubbling intra try break
try - command bubbling continue with finally
try - command bubbling intra try continue
try - command bubbling error replaced by return
try - command bubbling error replaced by return 2
try - command bubbling return replaced by error
try - exitTest with finally processing
try - try without matching catch
while
for
foreach
foreach-xpath
forjson
forxml
continue-break 1
continue-break 2
continue-break 3
continue-break 4
nested-loops
function
function-recursive
issue-2-function
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
GlobalFunctions
CallGlobalFunction
DefineFunctionParameters - Base
DefineFunctionParameters - With Default Values
StoreLocal - Function Scope
StoreGlobal - Function Scope
StoreGlobal - While Scope
StoreLocal - While Scope
Store - Behaves as StoreLocal
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
+ + +
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
README.html
+ + + + + + + + + + +
README
openhttp://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.html
+ + +
 
eval.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
eval
resetEmitted
emit"dilbert".isOneOf("dilbert","dogbert","mordac")
emit"bob".isOneOf("dilbert","dogbert","mordac")
emit"red".mapTo("primary", ["red","green","blue"])
emit"orange".mapTo("primary", ["red","green","blue"])
emit"red".translate("e", "E")
emit"red".translate(["red", "green", "blue"], ["blue", "red", "green"])
assertEmitted"true~false~primary~orange~rEd~blue"
+ + +
 
branching.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
branching
resetEmitted
emit"BEFORE"
gotoHERE
emit"A"
labelHERE
gotoIftrueTHERE
emit"B"
labelTHERE
skipNext
emit"C"
emit"AFTER"
assertEmitted"BEFORE~AFTER"
expectError"Target label 'NOWHERE' is not found"
gotoNOWHERE
expectError"Target label 'NOWHERE' is not found"
gotoIftrueNOWHERE
expectError"Requires a number > 1"
skipNext-1
expectError/.*random.* (is not |is un)defined/
skipNextrandom
+ + +
 
if-1.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-1
resetEmitted
emit"BEFORE"
iftrue
emit"truthy"
endIf
iffalse
emit"falsey"
endIf
iftrue
emit"A"
else
emit"B"
endIf
iffalse
emit"X"
else
emit"Y"
endIf
iffalse
emit"false teeth"
else
iftrue
emit"truthF"
else
emit"false false"
endIf
endIf
if"dilbert".isOneOf("dogbert","dilbert","wally")
emit"office mate"
endIf
if"dilbert".isOneOf("ratbert","alice","asok")
emit"mate"
else
emit"coffee mate"
endIf
if"mordac".isOneOf("bob the dinosaur","garbage man","mordac")
emit"cell mate"
else
emit"don't wait"
endIf
emit"AFTER"
assertEmitted"BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER"
+ + +
 
if-2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-2
resetEmitted
iftrue
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-a1y"
elseIftrue
emit"else-a2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-b1y"
elseIftrue
emit"elseIf-b2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-y"
else
emit"else-y"
endIf
assertEmitted"if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y"
+ + +
 
if-3.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-3
resetEmitted
foreachi2, 0, 1, 4, 3, 5
ifi == 0
emit"if-${i}"
elseIfi == 1
emit"elseIf-${i}"
elseIfi == 2
emit"elseIf-${i}"
elseIfi == 3
emit"elseIf-${i}"
else
emit"else-${i}"
endIf
endForeach
assertEmitted"elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5"
+ + +
 
try - noop.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - noop
log"-- no-op try --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-noop
emit"trying"
endTryt-noop
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + +
 
try - finally with no error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - finally with no error
log"-- try/finally, w/no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-fin
emit"trying"
finally
emit"finally"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~finally~/])"
+ + +
 
try - catch but no error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch but no error
log"-- try/catch, but no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc0
emit"trying"
catch
assertEval"should NEVER enter this catch block due to no error"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + +
 
try - catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error
log"-- catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc1
throw"blamo catch ALL"
assertEval"this command should not be reached, due to thrown"
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~caught 'blamo catch ALL'~/])"
+ + +
 
try - catch specific error then finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error then finally
log"-- catch specific error, then finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel-1
emit"([/"
tryt-spec-inner
emit"trying inner"
throw"blamo inner"
assertEval"this command should not be reached, due to throw"
catch/blamo inner/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-spec-inner
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
endTryt-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])"
+ + +
 
try - catch throw finally throw.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch throw finally throw
log"-- catch/throw, finally/throw --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytcf-trap
assertEvalselblocks.tcf.nestingLevel0
trytcf
emit"trying"
emit"throwing A"
throw"blamoA"
assertEval"this command should not be reached, due to thrown"
catch/blamoA/
emit"caught '" + _error.message + "'"
emit"throwing B"
throw"blamoB"
finally
emit"finally"
emit"throwing C"
throw"blamoC"
endTry
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])"
+ + +
 
try - bubble up to catch ALL.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL
log"-- bubble up to catch ALL --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-all-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-all-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
endTryt-all-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-all-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])"
+ + +
 
try - bubble up to catch ALL via finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL via finally
log"-- bubble up to catch ALL via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-allfin-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-allfin-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-allfin-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-allfin-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])"
+ + +
 
try - bubble up out of noop try to catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up out of noop try to catch specific error
log"-- bubble out of no-op try to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trynoop-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryop-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
endTryop-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrynoop-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])"
+ + +
 
try - bubble up to catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error
log"-- bubble up to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])"
+ + +
 
try - bubble up to catch specific error via finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error via finally
log"-- bubble up to catch specific error via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])"
+ + +
 
try - throw catch rethrow.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - throw catch rethrow
log"-- throw, catch, rethrow --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryouter
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryinner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing blamo1"
throw"blamo1"
assertEval"this command should not be reached, due to throw"
catch/blamo1/
emit"caught '" + _error.message + "'"
emit"throwing blamo2"
throw"blamo2"
endTryinner
catch/blamo2/
emit"caught '" + _error.message + "'"
endTryouter
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])"
+ + +
 
try - bubble out of nested function calls.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble out of nested function calls
log"-- bubble out of nested function calls --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-invoke
emit"trying"
emit"calling"
callsubBubn = 0
assertEval"this command should not be reached, due error thrown in function"
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-invoke
assertEvalselblocks.tcf.nestingLevel-1
functionsubBubn
trytcf-inner
emit"${n}) trying-inner"
ifn < 2
emit"${n}) calling"
callsubBubn = n+1
else
emit"${n}) throwing"
throw"blamo"
endIf
finally
emit"${n}) finally"
endTrytcf-inner
assertEvalselblocks.tcf.nestingLevel0
endFunction
emit"/])"
assertEmitted"([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])"
+ + +
 
try - command bubbling break with finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling, break with finally
log"-- command bubbling, break w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"${w}) trying"
ifw==2
emit"${w}) BREAK"
break
endIf
finally
emit"${w}) finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])"
+ + +
 
try - command bubbling intra try break.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try break
log"-- command bubbling, intra-try break --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) BREAK"
break
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) BREAK~finallying~/])"
+ + +
 
try - command bubbling continue with finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling continue with finally
log"-- command bubbling, continue w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"${w}) trying"
ifw==2
emit"${w}) CONTINUE"
continue
endIf
finally
emit"${w}) finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])"
+ + +
 
try - command bubbling intra try continue.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try continue
log"-- command bubbling, intra-try continue --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) CONTINUE"
continue
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])"
+ + +
 
try - command bubbling error replaced by return.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubA
emit"returned ${_result}"
functioncmdBubA
emit"in cmdBubA"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to return/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])"
+ + +
 
try - command bubbling error replaced by return 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return 2
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubB
emit"returned ${_result}"
functioncmdBubB
emit"in cmdBubB"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"throwing"
throw"short-lived error"
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to throw/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])"
+ + +
 
try - command bubbling return replaced by error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling return replaced by error
log"-- command bubbling, return replaced by error --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubC
emit"returned ${_result}"
functioncmdBubC
emit"in cmdBubC"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf-guardrail
assertEvalselblocks.tcf.nestingLevel0
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"throwing"
throw"this-error-replaces-return-1"
endTry
catch/this-error-replaces-return-1/
emit"caught '" + _error.message + "'"
assertEvalselblocks.tcf.nestingLevel0
endTry
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])"
+ + +
 
try - exitTest with finally processing.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - exitTest with finally processing
log"-- exitTest w/finally processing --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryabort
emit"trying"
emit"exitTest ..."
exitTest
finally
emit"finallying"
assertEmitted"([/~trying~exitTest ...~finallying"
resetEmitted
endTryabort
assertEval"this command should not be reached, due to exitTest above"
+ + +
 
try - try without matching catch.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - try without matching catch
log"-- try without matching catch --"
resetEmitted
assertEvalselblocks.tcf.nestingLevel-1
trymiss
assertEvaltruetrue
throw"blamo will NOT be caught at all"
assertEval"this command should not be reached"
catch/will NOT catch it/
log"caught miss '" + _error.message + "'"
finally
log"finally"
endTrymissCommand execution failure. Please search the user group at https://groups.google.com/forum/#!forum/selenium-users for error details from the log window.  The error message is: blamo will NOT be caught at all
assertEvalselblocks.tcf.nestingLevel-1
emit"trying"
+ + +
 
while.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsw
store3w
emit"START: ${w}"
whilew == 42
emit"SHOULD NEVER HAPPEN"
endWhile
whilew > 0
emit"iter=${w}"
storeEval${w}-1w
endWhile
emit"END: ${w}"
assertEmitted"START: 3~iter=3~iter=2~iter=1~END: 3"
+ + +
 
for.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsf
emit"START ${f}"
fors=0,f=3; f <= 5; f++
emit"iter=${f}.${s}"
endFor
emit"END ${f}"
assertEmitted"START $" + "{f}~iter=3.0~iter=4.0~iter=5.0~END $" + "{f}"
+ + +
 
foreach.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVars_i, fe
emit"START ${_i}-${fe}"
foreachfe"dilbert", "dogbert", "wally"
emit"${_i}) ${fe}"
endForeach
emit"END ${_i}-${fe}"
assertEmitted"START $" + "{_i}-$" + "{fe}~0) dilbert~1) dogbert~2) wally~END $" + "{_i}-$" + "{fe}"
+ + +
 
foreach-xpath.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreachX
resetEmitted
echo$x("//input")$x("//input")
echo$X("//input")$X("//input")
echobeginbegin
emit"START ${_i}) ${link}"
foreachlink$X("//input")
emit"${_i}) ${link}"
echo${link}[object HTMLInputElement]
endForeach
emit"END ${_i}) ${link}"
assertEmitted"START ${" + "_i}) ${" + "link}~0) [object HTMLInputElement]~1) [object HTMLInputElement]~2) [object HTMLInputElement]~END ${" + "_i}) ${" + "link}"
+ + +
 
forjson.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
ifglobalContext.onServer === true
store../data/forjson.jsonforJsonFileName
else
storedata/forjson.jsonforJsonFileName
endIf
resetEmitted
deleteVarsjname
emit"START ${jname}"
forJson${forJsonFileName}
emitjname
endForJson
emit"INTERMISSION ${jname}"
loadJsonVars${forJsonFileName}jname == "dogbert"
emit"END ${jname}"
assertEmitted"START $" + "{jname}~dilbert~dogbert~wally~INTERMISSION $" + "{jname}~END dogbert"
expectError"Requires a JSON file path or URL"
loadJsonVars
expectError"Multiple JSON objects are not valid for this command"
loadJsonVars${forJsonFileName}
expectError'"flubber" is not a boolean expression'
loadJsonVars${forJsonFileName}"flubber"
+ + +
 
forxml.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
resetEmitted
deleteVarsxname
emit"START ${xname}"
forXml${forXmlFileName}
emitxname
endForXml
emit"INTERMISSION ${xname}"
loadXmlVars${forXmlFileName}xname == "dogbert"
emit"END ${xname}"
assertEmitted"START $" + "{xname}~dilbert~dogbert~wally~INTERMISSION $" + "{xname}~END dogbert"
loadXmlVars${forXmlFileName}xname == "dogbert"
expectError"Requires an XML file path or URL"
loadXmlVars
expectError"Multiple XML elements are not valid for this command"
loadXmlVars${forXmlFileName}
expectError'"flubber" is not a boolean expression'
loadXmlVars${forXmlFileName}"flubber"
+ + +
 
continue-break 1.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 1
resetEmitted
deleteVarsf
forf=3; f <= 9; f++
continuef == 6
iff > 6
iff == 7
continue
else
break
endIf
endIf
emit"iter=${f}"
endFor
assertEmitted"iter=3~iter=4~iter=5"
+ + +
 
continue-break 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 2
resetEmitted
store0i
whilei++ < 10
continuei==3
breaki==5
emit"iter=${i}"
endWhile
assertEmitted"iter=1~iter=2~iter=4"
+ + +
 
continue-break 3.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 3
resetEmitted
foreachfe"dilbert","dogbert","wally"
continuefe=="dogbert"
breakfe=="wally"
emit"iter=${fe}"
endForeach
assertEmitted"iter=dilbert"
+ + +
 
continue-break 4.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 4
resetEmitted
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
forXml${forXmlFileName}
continuexname=="dogbert"
breakxname=="wally"
emit"iter=${xname}"
endForXml
assertEmitted"iter=dilbert"
+ + +
 
nested-loops.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsi, n, uname
startTimer
store2i
emit"START ${i}"
whilei > 0
emit"while=${i}"
foreachuname"dilbert", "dogbert"
emit"foreach=${uname}"
forn = 2; n <=3; n++
emit"FOR=${n}"
forn = 7; n <= 8; n++
emit"for=${n}"
endFor
endFor
emit"endFor ${n}"
endForeach
storeEval${i}-1i
endWhile
emit"END ${i}"
timerElapsed
assertEmitted"START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2"
+ + +
 
function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
subtest
deleteVarssname, srole
assertEval"START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}"true
calldoSomethingsname = "dilbert,Q", srole = "goof"
assertEval"${_result}" === "sname=dilbert,Q,srole=goof"true
deleteVarssname, srole
functiondoSomethingsname
return"sname=${sname},srole=${srole}"
endFunctiondoSomething
deleteVarssname, srole
calldoSomethingsname = "dogbert", srole = "woof"
assertEval"${_result}" === "sname=dogbert,srole=woof"true
deleteVarssname, srole
calldoSomethingsname = "ratbert", srole = "squeak"
assertEval"${_result}" === "sname=ratbert,srole=squeak"true
deleteVarssname, srole
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
assertEval"${_result}" === "sname=${sname},srole=super=user"true
deleteVarssname, srole
endForeach
assertEval"DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}"true
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
deleteVarssname, srole
scriptdoDeprecatedsname
return"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEval"${_result}" === "sname=wally,srole=lazy"true
deleteVarssname, srole
+ + +
 
function-recursive.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
factorial
resetEmitted
deleteVarsdegree, n, _result, ud
store7degree
startTimerfactorial ${degree}
callfacn=degree
timerElapsed
emitdegree + "!=" + _result
functionfacn
ifn <= 1
return1
else
callfacn = n-1
emit_result
returnn * _result
endIf
endFunction
functionuno
emit"UNO"
storeEval${ud}-1ud
ifud > 0
calldue
endIf
endFunctionuno
functiondue
emit"DUE"
storeEval${ud}-1ud
ifud > 0
calluno
endIf
endFunctiondue
store5ud
calluno
assertEmitted"1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO"
+ + +
 
issue-2-function.html
+ + + + + + + + + + + + + + + + + + + + + + + + +
issue#2
functionxyz
log'here'
endFunction
callxyz
+ + +
 
exitTest - base case.html
+ + + + + + + + + + + + + + + + + + + + +
exitTest - base case
resetEmitted
exitTest
throw"shouldn't happen"
+ + +
 
exitTest - from within a loop.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a loop
fori=0; i < 5; i++
ifi == 3
exitTest
endIf
ifi === 3
throw"This test should exit when the increment gets to 3, and this should never be thrown."
endIf
endFor
+ + +
 
exitTest - from within a function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a function
calldoSubExit
throw"shouldn't happen"
functiondoSubExit
exitTest
endFunctiondoSubExit
+ + +
 
GlobalFunctions.html
+ + + + + + + + + + + + + + + + + + + + + + + + +
functions
getEvalglobalStoredVars = {};
functionsetGlobalVar
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
+ + +
 
CallGlobalFunction.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + +
 
DefineFunctionParameters - Base.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - Base
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionbobx,y
assertEval"${x}" === "overwritten"true
assertEvalstoredVars.y === undefinedtrue
endFunction
callbobx="overwritten"
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEvalstoredVars.y === undefinedfalse
assertEval"${y}" === "original";true
+ + +
 
DefineFunctionParameters - With Default Values.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - With Default Values
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionleakTestx="fn default x",y="fn default y"
storeoverwrittenx
storeoverwritteny
endFunction
functiondefaultsTestx="fn default x",y="fn default y"
assertEval${x} === "fn default x"true
store"overwritten"x
assertEval${x} === "overwritten"true
assertEval${y} === "fn default y"true
store"overwritten"y
assertEval${y} === "overwritten"true
endFunction
calldefaultsTest
callleakTest
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTesty = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten", y = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
+ + +
 
StoreLocal - Function Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
StoreGlobal - Function Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - Function Scope
functionblockScopeVars
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endFunction
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + +
 
StoreGlobal - While Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - While Scope
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
store1i
whilei > 0
store0i
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endWhile
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + +
 
StoreLocal - While Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - While Scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
store1i
whilei > 0
store0i
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endWhile
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
Store - Behaves as StoreLocal.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store - Behaves as StoreLocal
functionblockScopeVars
storethis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
Function - Can Return Value.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Function - Can Return Value
functionreturnsValue
return"banana"
endFunction
callreturnsValue
assertEval"${_result}" === "banana"true
+ + +
 
StoreAt - Function Scope Nesting.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - Function Scope Nesting
functionstorel
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
endFunction
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
callstorel
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + +
 
StoreAt - While Scope Nesting.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - While Scope Nesting
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
storeLocal3x
whilex !== 0
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
storeEvalLocalx -= 1
endWhile
deleteVarx
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + +
 
sendkeys keys are preserved.html
+ + + + + + + + + + + + + + + + + + + + +
sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ + +
 
+info: Starting test /selenium-server/tests/README.html
+info: Executing: |open | http://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.html |  |
+info: Starting test /selenium-server/tests/eval.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "dilbert".isOneOf("dilbert","dogbert","mordac") |  |
+info: Executing: |emit | "bob".isOneOf("dilbert","dogbert","mordac") |  |
+info: Executing: |emit | "red".mapTo("primary", ["red","green","blue"]) |  |
+info: Executing: |emit | "orange".mapTo("primary", ["red","green","blue"]) |  |
+info: Executing: |emit | "red".translate("e", "E") |  |
+info: Executing: |emit | "red".translate(["red", "green", "blue"], ["blue", "red", "green"]) |  |
+info: Executing: |assertEmitted | "true~false~primary~orange~rEd~blue" |  |
+info: Starting test /selenium-server/tests/branching.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "BEFORE" |  |
+info: Executing: |goto | HERE |  |
+info: [SelBlocks] branch => @5: [label|HERE]
+info: Executing: |label | HERE |  |
+info: Executing: |gotoIf | true | THERE |
+info: [SelBlocks] branch => @8: [label|THERE]
+info: Executing: |label | THERE |  |
+info: Executing: |skipNext |  |  |
+info: [SelBlocks] branch => @11: [emit|"AFTER"]
+info: Executing: |emit | "AFTER" |  |
+info: Executing: |assertEmitted | "BEFORE~AFTER" |  |
+info: Executing: |expectError | "Target label 'NOWHERE' is not found" |  |
+info: Executing: |goto | NOWHERE |  |
+error: [SelBlocks] Error @14: [goto|NOWHERE] Target label 'NOWHERE' is not found.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Target label 'NOWHERE' is not found" |  |
+info: Executing: |gotoIf | true | NOWHERE |
+error: [SelBlocks] Error @16: [gotoIf|true|NOWHERE] Target label 'NOWHERE' is not found.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Requires a number > 1" |  |
+info: Executing: |skipNext | -1 |  |
+error: [SelBlocks] Error @18: [skipNext|-1] Requires a number > 1
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | /.*random.* (is not |is un)defined/ |  |
+info: Executing: |skipNext | random |  |
+error: [SelBlocks] Error  While evaluating Javascript expression: random
+warn: [SelBlocks] __Stack Trace__
+info: Starting test /selenium-server/tests/if-1.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "BEFORE" |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "truthy" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @8: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "A" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @16: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "Y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @21: [else]
+info: Executing: |else |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "truthF" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @26: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "dilbert".isOneOf("dogbert","dilbert","wally") |  |
+info: Executing: |emit | "office mate" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "dilbert".isOneOf("ratbert","alice","asok") |  |
+info: [SelBlocks] branch => @33: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "coffee mate" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "mordac".isOneOf("bob the dinosaur","garbage man","mordac") |  |
+info: Executing: |emit | "cell mate" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @40: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "AFTER" |  |
+info: Executing: |assertEmitted | "BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER" |  |
+info: Starting test /selenium-server/tests/if-2.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "if-y" |  |
+info: Executing: |elseIf | true |  |
+info: [SelBlocks] branch => @6: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @9: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @14: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-a1y" |  |
+info: Executing: |elseIf | true |  |
+info: [SelBlocks] branch => @18: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @21: [elseIf|false]
+info: Executing: |elseIf | false |  |
+info: [SelBlocks] branch => @23: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-b2y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @28: [elseIf|false]
+info: Executing: |elseIf | false |  |
+info: [SelBlocks] branch => @30: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |assertEmitted | "if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y" |  |
+info: Starting test /selenium-server/tests/if-3.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: Executing: |emit | "if-${i}" |  |
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-${i}" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-${i}" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: [SelBlocks] branch => @14: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEmitted | "elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5" |  |
+info: Starting test /selenium-server/tests/try%20-%20noop.html
+info: Executing: |log | "-- no-op try --" |  |
+info: [SelBench] -- no-op try --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-noop |  |
+warn: [SelBlocks] @5: [try|t-noop] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying" |  |
+info: Executing: |endTry | t-noop |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20finally%20with%20no%20error.html
+info: Executing: |log | "-- try/finally, w/no error --" |  |
+info: [SelBench] -- try/finally, w/no error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-fin |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20but%20no%20error.html
+info: Executing: |log | "-- try/catch, but no error --" |  |
+info: [SelBench] -- try/catch, but no error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tc0 |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |catch |  |  |
+info: [SelBlocks] branch => @9: [endTry]
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20specific%20error.html
+info: Executing: |log | "-- catch specific error --" |  |
+info: [SelBench] -- catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tc1 |  |
+info: Executing: |throw | "blamo catch ALL" |  |
+info: [SelBlocks] @6, error has been caught :: 
+info: [SelBlocks] branch => @8: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~caught 'blamo catch ALL'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20specific%20error%20then%20finally.html
+info: Executing: |log | "-- catch specific error, then finally --" |  |
+info: [SelBench] -- catch specific error, then finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-spec-outer |  |
+warn: [SelBlocks] @5: [try|t-spec-outer] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "([/" |  |
+info: Executing: |try | t-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |throw | "blamo inner" |  |
+info: [SelBlocks] @11, error has been caught :: /blamo inner/
+info: [SelBlocks] branch => @13: [catch|/blamo inner/]
+info: Executing: |catch | /blamo inner/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | t-spec-inner |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |endTry | t-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20throw%20finally%20throw.html
+info: Executing: |log | "-- catch/throw, finally/throw --" |  |
+info: [SelBench] -- catch/throw, finally/throw --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tcf-trap |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "throwing A" |  |
+info: Executing: |throw | "blamoA" |  |
+info: [SelBlocks] @10, error has been caught :: /blamoA/
+info: [SelBlocks] branch => @12: [catch|/blamoA/]
+info: Executing: |catch | /blamoA/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |emit | "throwing B" |  |
+info: Executing: |throw | "blamoB" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @16: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |emit | "throwing C" |  |
+info: Executing: |throw | "blamoC" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @20: [endTry]
+info: Executing: |endTry |  |  |
+info: [SelBlocks] @20, error has been caught :: @19 
+info: [SelBlocks] branch => @22: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20ALL.html
+info: Executing: |log | "-- bubble up to catch ALL --" |  |
+info: [SelBench] -- bubble up to catch ALL --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-all-outer |  |
+info: Executing: |emit | "trying-outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-all-inner |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |throw | "blamo try-catch-finally" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @14: [endTry|t-all-inner]
+info: Executing: |endTry | t-all-inner |  |
+info: [SelBlocks] @14, error has been caught :: @10 
+info: [SelBlocks] branch => @16: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught-outer '" + _error.message + "'" |  |
+info: Executing: |endTry | t-all-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20ALL%20via%20finally.html
+info: Executing: |log | "-- bubble up to catch ALL via finally --" |  |
+info: [SelBench] -- bubble up to catch ALL via finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-allfin-outer |  |
+info: Executing: |emit | "trying-outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-allfin-inner |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |throw | "blamo try-catch-finally" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | t-allfin-inner |  |
+info: [SelBlocks] @16, error has been caught :: @10 
+info: [SelBlocks] branch => @18: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught-outer '" + _error.message + "'" |  |
+info: Executing: |endTry | t-allfin-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20out%20of%20noop%20try%20to%20catch%20specific%20error.html
+info: Executing: |log | "-- bubble out of no-op try to catch specific error --" |  |
+info: [SelBench] -- bubble out of no-op try to catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | noop-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | op-inner |  |
+warn: [SelBlocks] @8: [try|op-inner] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @14: [endTry|op-inner]
+info: Executing: |endTry | op-inner |  |
+info: [SelBlocks] @14, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @15: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | noop-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20specific%20error.html
+info: Executing: |log | "-- bubble up to catch specific error --" |  |
+info: [SelBench] -- bubble up to catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-inner |  |
+info: [SelBlocks] @16, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @17: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry | bub-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20specific%20error%20via%20finally.html
+info: Executing: |log | "-- bubble up to catch specific error via finally --" |  |
+info: [SelBench] -- bubble up to catch specific error via finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-inner |  |
+info: [SelBlocks] @16, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @17: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20throw%20catch%20rethrow.html
+info: Executing: |log | "-- throw, catch, rethrow --" |  |
+info: [SelBench] -- throw, catch, rethrow --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing blamo1" |  |
+info: Executing: |throw | "blamo1" |  |
+info: [SelBlocks] @12, error has been caught :: /blamo1/
+info: [SelBlocks] branch => @14: [catch|/blamo1/]
+info: Executing: |catch | /blamo1/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |emit | "throwing blamo2" |  |
+info: Executing: |throw | "blamo2" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @18: [endTry|inner]
+info: Executing: |endTry | inner |  |
+info: [SelBlocks] @18, error has been caught :: @17 /blamo2/
+info: [SelBlocks] branch => @19: [catch|/blamo2/]
+info: Executing: |catch | /blamo2/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry | outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20out%20of%20nested%20function%20calls.html
+info: Executing: |log | "-- bubble out of nested function calls --" |  |
+info: [SelBench] -- bubble out of nested function calls --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-invoke |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | subBub | n = 0 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: Executing: |emit | "${n}) calling" |  |
+info: Executing: |call | subBub | n = n+1 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: Executing: |emit | "${n}) calling" |  |
+info: Executing: |call | subBub | n = n+1 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: [SelBlocks] branch => @22: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "${n}) throwing" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] @28, error has been caught :: @28 /blamo/
+info: [SelBlocks] branch => @10: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-invoke |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |function | subBub | n |
+info: [SelBlocks] branch => @30: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20break%20with%20finally.html
+info: Executing: |log | "-- command bubbling, break w/finally --" |  |
+info: [SelBench] -- command bubbling, break w/finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) BREAK" |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] Command @11: [break], suspended while finally block runs
+info: [SelBlocks] branch => @13: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @11: [break]
+info: [SelBlocks] branch => @11: [break]
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @18: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20intra%20try%20break.html
+info: Executing: |log | "-- command bubbling, intra-try break --" |  |
+info: [SelBench] -- command bubbling, intra-try break --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) BREAK" |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~while'g~3) iterating~2) BREAK~finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20continue%20with%20finally.html
+info: Executing: |log | "-- command bubbling, continue w/finally --" |  |
+info: [SelBench] -- command bubbling, continue w/finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) CONTINUE" |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] Command @11: [continue], suspended while finally block runs
+info: [SelBlocks] branch => @13: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @11: [continue]
+info: [SelBlocks] branch => @11: [continue]
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: [SelBlocks] branch => @18: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20intra%20try%20continue.html
+info: Executing: |log | "-- command bubbling, intra-try continue --" |  |
+info: [SelBench] -- command bubbling, intra-try continue --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) CONTINUE" |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20error%20replaced%20by%20return.html
+info: Executing: |log | "-- command bubbling, error replaced by return --" |  |
+info: [SelBench] -- command bubbling, error replaced by return --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubA |  |
+info: [SelBlocks] branch => @7: [function|cmdBubA]
+info: Executing: |function | cmdBubA |  |
+info: Executing: |emit | "in cmdBubA" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "returning (1)" |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] Command @13: [return|1], suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "returning (2)" |  |
+info: Executing: |return | 2 |  |
+info: Executing: |endTry |  |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @17: [return|2]
+info: [SelBlocks] branch => @17: [return|2]
+info: Executing: |return | 2 |  |
+info: [SelBlocks] branch => @5: [call|cmdBubA]
+info: Executing: |call | cmdBubA |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubA |  |
+info: [SelBlocks] branch => @20: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20error%20replaced%20by%20return%202.html
+info: Executing: |log | "-- command bubbling, error replaced by return --" |  |
+info: [SelBench] -- command bubbling, error replaced by return --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubB |  |
+info: [SelBlocks] branch => @7: [function|cmdBubB]
+info: Executing: |function | cmdBubB |  |
+info: Executing: |emit | "in cmdBubB" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "throwing" |  |
+info: Executing: |throw | "short-lived error" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "returning (2)" |  |
+info: Executing: |return | 2 |  |
+info: Executing: |endTry |  |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @17: [return|2]
+info: [SelBlocks] branch => @17: [return|2]
+info: Executing: |return | 2 |  |
+info: [SelBlocks] branch => @5: [call|cmdBubB]
+info: Executing: |call | cmdBubB |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubB |  |
+info: [SelBlocks] branch => @20: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20return%20replaced%20by%20error.html
+info: Executing: |log | "-- command bubbling, return replaced by error --" |  |
+info: [SelBench] -- command bubbling, return replaced by error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubC |  |
+info: [SelBlocks] branch => @7: [function|cmdBubC]
+info: Executing: |function | cmdBubC |  |
+info: Executing: |emit | "in cmdBubC" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf-guardrail |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "returning (1)" |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] Command @15: [return|1], suspended while finally block runs
+info: [SelBlocks] branch => @16: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "throwing" |  |
+info: Executing: |throw | "this-error-replaces-return-1" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @20: [endTry]
+info: Executing: |endTry |  |  |
+info: [SelBlocks] @20, error has been caught :: @19 /this-error-replaces-return-1/
+info: [SelBlocks] branch => @21: [catch|/this-error-replaces-return-1/]
+info: Executing: |catch | /this-error-replaces-return-1/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |endTry |  |  |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @5: [call|cmdBubC]
+info: Executing: |call | cmdBubC |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubC |  |
+info: [SelBlocks] branch => @25: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20exitTest%20with%20finally%20processing.html
+info: Executing: |log | "-- exitTest w/finally processing --" |  |
+info: [SelBench] -- exitTest w/finally processing --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | abort |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "exitTest ..." |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] Command @8: [exitTest], suspended while finally block runs
+info: [SelBlocks] branch => @9: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |assertEmitted | "([/~trying~exitTest ...~finallying" |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |endTry | abort |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @8: [exitTest]
+info: [SelBlocks] branch => @8: [exitTest]
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/try%20-%20try%20without%20matching%20catch.html
+info: Executing: |log | "-- try without matching catch --" |  |
+info: [SelBench] -- try without matching catch --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | miss |  |
+info: Executing: |assertEval | true | true |
+info: script is: true
+info: Executing: |throw | "blamo will NOT be caught at all" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @10: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |log | "finally" |  |
+info: [SelBench] finally
+info: Executing: |endTry | miss |  |
+error: [SelBlocks] Error was not caught: 'blamo will NOT be caught at all'
+error: Unexpected Exception: blamo will NOT be caught at all
+error: Exception details: name -> SelblocksError, message -> blamo will NOT be caught at all, idx -> 5
+warn: currentTest.recordFailure: Command execution failure. Please search the user group at https://groups.google.com/forum/#!forum/selenium-users for error details from the log window.  The error message is: blamo will NOT be caught at all
+info: Starting test /selenium-server/tests/while.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | w |  |
+info: Executing: |store | 3 | w |
+info: Executing: |emit | "START: ${w}" |  |
+info: Executing: |while | w == 42 |  |
+info: [SelBlocks] branch => @7: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 3-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 2-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 1-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: [SelBlocks] branch => @11: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |emit | "END: ${w}" |  |
+info: Executing: |assertEmitted | "START: 3~iter=3~iter=2~iter=1~END: 3" |  |
+info: Starting test /selenium-server/tests/for.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | f |  |
+info: Executing: |emit | "START ${f}" |  |
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: [SelBlocks] branch => @6: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "END ${f}" |  |
+info: Executing: |assertEmitted | "START $" + "{f}~iter=3.0~iter=4.0~iter=5.0~END $" + "{f}" |  |
+info: Starting test /selenium-server/tests/foreach.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | _i, fe |  |
+info: Executing: |emit | "START ${_i}-${fe}" |  |
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: [SelBlocks] branch => @6: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "END ${_i}-${fe}" |  |
+info: Executing: |assertEmitted | "START $" + "{_i}-$" + "{fe}~0) dilbert~1) dogbert~2) wally~END $" + "{_i}-$" + "{fe}" |  |
+info: Starting test /selenium-server/tests/foreach-xpath.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |echo | $x("//input") |  |
+info: Executing: |echo | $X("//input") |  |
+info: Executing: |echo | begin |  |
+info: Executing: |emit | "START ${_i}) ${link}" |  |
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} | [object HTMLInputElement] |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} | [object HTMLInputElement] |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: [SelBlocks] branch => @9: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "END ${_i}) ${link}" |  |
+info: Executing: |assertEmitted | "START ${" + "_i}) ${" + "link}~0) [object HTMLInputElement]~1) [object HTMLInputElement]~2) [object HTMLInputElement]~END ${" + "_i}) ${" + "link}" |  |
+info: Starting test /selenium-server/tests/forjson.html
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forjson.json | forJsonFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @5: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | jname |  |
+info: Executing: |emit | "START ${jname}" |  |
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: [SelBlocks] Reading from: ../data/forjson.json
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: [SelBlocks] branch => @11: [endForJson]
+info: Executing: |endForJson |  |  |
+info: Executing: |emit | "INTERMISSION ${jname}" |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} | jname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forjson.json
+info: Executing: |emit | "END ${jname}" |  |
+info: Executing: |assertEmitted | "START $" + "{jname}~dilbert~dogbert~wally~INTERMISSION $" + "{jname}~END dogbert" |  |
+info: Executing: |expectError | "Requires a JSON file path or URL" |  |
+info: Executing: |loadJsonVars |  |  |
+error: [SelBlocks] Error @17: [loadJsonVars] Requires a JSON file path or URL.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Multiple JSON objects are not valid for this command" |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} |  |
+info: [SelBlocks] Reading from: ../data/forjson.json
+error: [SelBlocks] Error @19: [loadJsonVars|${forJsonFileName}] Multiple JSON objects are not valid for this command. (A specific JSON object can be selected by specifying: name="value".)
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | '"flubber" is not a boolean expression' |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} | "flubber" |
+info: [SelBlocks] Reading from: ../data/forjson.json
+error: [SelBlocks] Error @21: [loadJsonVars|${forJsonFileName}|"flubber"], "flubber" is not a boolean expression
+warn: [SelBlocks] __Stack Trace__
+info: Starting test /selenium-server/tests/forxml.html
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forxml.xml | forXmlFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @5: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | xname |  |
+info: Executing: |emit | "START ${xname}" |  |
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] branch => @11: [endForXml]
+info: Executing: |endForXml |  |  |
+info: Executing: |emit | "INTERMISSION ${xname}" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | xname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |emit | "END ${xname}" |  |
+info: Executing: |assertEmitted | "START $" + "{xname}~dilbert~dogbert~wally~INTERMISSION $" + "{xname}~END dogbert" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | xname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |expectError | "Requires an XML file path or URL" |  |
+info: Executing: |loadXmlVars |  |  |
+error: [SelBlocks] Error @18: [loadXmlVars] Requires an XML file path or URL.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | "Multiple XML elements are not valid for this command" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+error: [SelBlocks] Error @20: [loadXmlVars|${forXmlFileName}] Multiple XML elements are not valid for this command. (A specific XML element can be selected by specifying: name="value".)
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |expectError | '"flubber" is not a boolean expression' |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | "flubber" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+error: [SelBlocks] Error @22: [loadXmlVars|${forXmlFileName}|"flubber"], "flubber" is not a boolean expression
+warn: [SelBlocks] __Stack Trace__
+info: Starting test /selenium-server/tests/continue-break%201.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | f |  |
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: Executing: |if | f == 7 |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: Executing: |if | f == 7 |  |
+info: [SelBlocks] branch => @8: [else]
+info: Executing: |else |  |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @13: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |assertEmitted | "iter=3~iter=4~iter=5" |  |
+info: Starting test /selenium-server/tests/continue-break%202.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |store | 0 | i |
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: [SelBlocks] branch => @7: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEmitted | "iter=1~iter=2~iter=4" |  |
+info: Starting test /selenium-server/tests/continue-break%203.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: Executing: |break | fe=="wally" |  |
+info: Executing: |emit | "iter=${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|fe|"dilbert","dogbert","wally"]
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: [SelBlocks] branch => @2: [foreach|fe|"dilbert","dogbert","wally"]
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: Executing: |break | fe=="wally" |  |
+info: [SelBlocks] branch => @6: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEmitted | "iter=dilbert" |  |
+info: Starting test /selenium-server/tests/continue-break%204.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forxml.xml | forXmlFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @6: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |continue | xname=="dogbert" |  |
+info: Executing: |break | xname=="wally" |  |
+info: Executing: |emit | "iter=${xname}" |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @7: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |continue | xname=="dogbert" |  |
+info: [SelBlocks] branch => @7: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |continue | xname=="dogbert" |  |
+info: Executing: |break | xname=="wally" |  |
+info: [SelBlocks] branch => @11: [endForXml]
+info: Executing: |endForXml |  |  |
+info: Executing: |assertEmitted | "iter=dilbert" |  |
+info: Starting test /selenium-server/tests/nested-loops.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | i, n, uname |  |
+info: Executing: |startTimer |  |  |
+info: Executing: |store | 2 | i |
+info: Executing: |emit | "START ${i}" |  |
+info: Executing: |while | i > 0 |  |
+info: Executing: |emit | "while=${i}" |  |
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: [SelBlocks] branch => @17: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |storeEval | ${i}-1 | i |
+info: script is: 2-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: Executing: |emit | "while=${i}" |  |
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: [SelBlocks] branch => @17: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |storeEval | ${i}-1 | i |
+info: script is: 1-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @19: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |emit | "END ${i}" |  |
+info: Executing: |timerElapsed |  |  |
+info: [SelBench] 0.799 sec elapsed: 
+info: Executing: |assertEmitted | "START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2" |  |
+info: Starting test /selenium-server/tests/function.html
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |assertEval | "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}" | true |
+info: script is: "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}"
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @3: [call|doSomething|sname = "dilbert,Q", srole = "goof"]
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: Executing: |assertEval | "${_result}" === "sname=dilbert,Q,srole=goof" | true |
+info: script is: "sname=dilbert,Q,srole=goof" === "sname=dilbert,Q,srole=goof"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |function | doSomething | sname |
+info: [SelBlocks] branch => @8: [endFunction|doSomething]
+info: Executing: |endFunction | doSomething |  |
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @10: [call|doSomething|sname = "dogbert", srole = "woof"]
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: Executing: |assertEval | "${_result}" === "sname=dogbert,srole=woof" | true |
+info: script is: "sname=dogbert,srole=woof" === "sname=dogbert,srole=woof"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @13: [call|doSomething|sname = "ratbert", srole = "squeak"]
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: Executing: |assertEval | "${_result}" === "sname=ratbert,srole=squeak" | true |
+info: script is: "sname=ratbert,srole=squeak" === "sname=ratbert,srole=squeak"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @17: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |assertEval | "${_result}" === "sname=${sname},srole=super=user" | true |
+info: script is: "sname=asok,srole=super=user" === "sname=asok,srole=super=user"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @17: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |assertEval | "${_result}" === "sname=${sname},srole=super=user" | true |
+info: script is: "sname=alice,srole=super=user" === "sname=alice,srole=super=user"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: [SelBlocks] branch => @20: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEval | "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}" | true |
+info: script is: "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}"
+info: Executing: |expectError | "Function does not exist: NONEXISTENT" |  |
+info: Executing: |call | NONEXISTENT |  |
+error: [SelBlocks] Error @23: [call|NONEXISTENT] Function does not exist: NONEXISTENT
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |script | doDeprecated | sname |
+warn: [SelBlocks] The script command has been deprecated and will be removed in future releases. Please use function instead.
+info: [SelBlocks] branch => @27: [endScript|doDeprecated]
+info: Executing: |endScript | doDeprecated |  |
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: [SelBlocks] branch => @25: [script|doDeprecated|sname]
+info: Executing: |script | doDeprecated | sname |
+warn: [SelBlocks] The script command has been deprecated and will be removed in future releases. Please use function instead.
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @28: [call|doDeprecated|sname = "wally", srole = "lazy"]
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: Executing: |assertEval | "${_result}" === "sname=wally,srole=lazy" | true |
+info: script is: "sname=wally,srole=lazy" === "sname=wally,srole=lazy"
+info: Executing: |deleteVars | sname, srole |  |
+info: Starting test /selenium-server/tests/function-recursive.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | degree, n, _result, ud |  |
+info: Executing: |store | 7 | degree |
+info: Executing: |startTimer |  | factorial ${degree} |
+info: Executing: |call | fac | n=degree |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @5: [call|fac|n=degree]
+info: Executing: |call | fac | n=degree |
+info: Executing: |timerElapsed |  |  |
+info: [SelBench] 0.309 sec elapsed: factorial 7
+info: Executing: |emit | degree + "!=" + _result |  |
+info: Executing: |function | fac | n |
+info: [SelBlocks] branch => @16: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |function | uno |  |
+info: [SelBlocks] branch => @23: [endFunction|uno]
+info: Executing: |endFunction | uno |  |
+info: Executing: |function | due |  |
+info: [SelBlocks] branch => @30: [endFunction|due]
+info: Executing: |endFunction | due |  |
+info: Executing: |store | 5 | ud |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 5-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | due |  |
+info: [SelBlocks] branch => @24: [function|due]
+info: Executing: |function | due |  |
+info: Executing: |emit | "DUE" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 4-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 3-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | due |  |
+info: [SelBlocks] branch => @24: [function|due]
+info: Executing: |function | due |  |
+info: Executing: |emit | "DUE" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 2-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 1-1
+info: Executing: |if | ud > 0 |  |
+info: [SelBlocks] branch => @22: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @28: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | due |  |
+info: [SelBlocks] branch => @21: [call|due]
+info: Executing: |call | due |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @28: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | due |  |
+info: [SelBlocks] branch => @21: [call|due]
+info: Executing: |call | due |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @32: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |assertEmitted | "1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO" |  |
+info: Starting test /selenium-server/tests/issue-2-function.html
+info: Executing: |function | xyz |  |
+info: [SelBlocks] branch => @3: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | xyz |  |
+info: [SelBlocks] branch => @1: [function|xyz]
+info: Executing: |function | xyz |  |
+info: Executing: |log | 'here' |  |
+info: [SelBench] here
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @4: [call|xyz]
+info: Executing: |call | xyz |  |
+info: Starting test /selenium-server/tests/exitTest%20-%20base%20case.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/exitTest%20-%20from%20within%20a%20loop.html
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/exitTest%20-%20from%20within%20a%20function.html
+info: Executing: |call | doSubExit |  |
+info: [SelBlocks] branch => @3: [function|doSubExit]
+info: Executing: |function | doSubExit |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/GlobalFunctions.html
+info: Executing: |getEval | globalStoredVars = {}; |  |
+info: script is: globalStoredVars = {};
+info: Executing: |function | setGlobalVar |  |
+info: [SelBlocks] branch => @4: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Starting test /selenium-server/tests/CallGlobalFunction.html
+info: Executing: |getEval | globalStoredVars.aGlobalVar = "reset"; |  |
+info: script is: globalStoredVars.aGlobalVar = "reset";
+info: Executing: |assertNotEval | globalStoredVars.aGlobalVar; | set |
+info: script is: globalStoredVars.aGlobalVar;
+info: Executing: |assertEval | globalStoredVars.aGlobalVar; | reset |
+info: script is: globalStoredVars.aGlobalVar;
+info: Executing: |call | GlobalFunctions.setGlobalVar |  |
+info: [SelBlocks] branch => @2: [assertNotEval|globalStoredVars.aGlobalVar;|set]
+info: Executing: |function | setGlobalVar |  |
+info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; |  |
+info: script is: globalStoredVars.aGlobalVar = "set";
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @4: [call|GlobalFunctions.setGlobalVar]
+info: Executing: |call | GlobalFunctions.setGlobalVar |  |
+info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set |
+info: script is: globalStoredVars.aGlobalVar;
+info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20Base.html
+info: Executing: |store | original | x |
+info: Executing: |store | original | y |
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |function | bob | x,y |
+info: [SelBlocks] branch => @8: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | bob | x="overwritten" |
+info: [SelBlocks] branch => @5: [function|bob|x,y]
+info: Executing: |function | bob | x,y |
+info: Executing: |assertEval | "${x}" === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |assertEval | storedVars.y === undefined | true |
+info: script is: storedVars.y === undefined
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @9: [call|bob|x="overwritten"]
+info: Executing: |call | bob | x="overwritten" |
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | storedVars.y === undefined | false |
+info: script is: storedVars.y === undefined
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20With%20Default%20Values.html
+info: Executing: |store | original | x |
+info: Executing: |store | original | y |
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: [SelBlocks] branch => @8: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |function | defaultsTest | x="fn default x",y="fn default y" |
+info: [SelBlocks] branch => @16: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | defaultsTest |  |
+info: [SelBlocks] branch => @9: [function|defaultsTest|x="fn default x",y="fn default y"]
+info: Executing: |function | defaultsTest | x="fn default x",y="fn default y" |
+info: Executing: |assertEval | ${x} === "fn default x" | true |
+info: script is: "fn default x" === "fn default x"
+info: Executing: |store | "overwritten" | x |
+info: Executing: |assertEval | ${x} === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |assertEval | ${y} === "fn default y" | true |
+info: script is: "fn default y" === "fn default y"
+info: Executing: |store | "overwritten" | y |
+info: Executing: |assertEval | ${y} === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @17: [call|defaultsTest]
+info: Executing: |call | defaultsTest |  |
+info: Executing: |call | leakTest |  |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @18: [call|leakTest]
+info: Executing: |call | leakTest |  |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | y = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @25: [call|leakTest|y = "overwritten"]
+info: Executing: |call | leakTest | y = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | x = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @32: [call|leakTest|x = "overwritten"]
+info: Executing: |call | leakTest | x = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | x = "overwritten", y = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @39: [call|leakTest|x = "overwritten", y = "overwritten"]
+info: Executing: |call | leakTest | x = "overwritten", y = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Starting test /selenium-server/tests/StoreLocal%20-%20Function%20Scope.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |storeLocal | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @12: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/StoreGlobal%20-%20Function%20Scope.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.g = null; |  |
+info: script is: storedVarsGlobal.g = null;
+info: Executing: |assertEval | storedVarsGlobal.g === null; | true |
+info: script is: storedVarsGlobal.g === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |storeGlobal | this is stored globally | g |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @10: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Starting test /selenium-server/tests/StoreGlobal%20-%20While%20Scope.html
+info: Executing: |getEval | storedVarsGlobal.g = null; |  |
+info: script is: storedVarsGlobal.g = null;
+info: Executing: |assertEval | storedVarsGlobal.g === null; | true |
+info: script is: storedVarsGlobal.g === null;
+info: Executing: |store | 1 | i |
+info: Executing: |while | i > 0 |  |
+info: Executing: |store | 0 | i |
+info: Executing: |storeGlobal | this is stored globally | g |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @4: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @11: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Starting test /selenium-server/tests/StoreLocal%20-%20While%20Scope.html
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |store | 1 | i |
+info: Executing: |while | i > 0 |  |
+info: Executing: |store | 0 | i |
+info: Executing: |storeLocal | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @13: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/Store%20-%20Behaves%20as%20StoreLocal.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |store | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @12: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/Function%20-%20Can%20Return%20Value.html
+info: Executing: |function | returnsValue |  |
+info: [SelBlocks] branch => @3: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | returnsValue |  |
+info: [SelBlocks] branch => @1: [function|returnsValue]
+info: Executing: |function | returnsValue |  |
+info: Executing: |return | "banana" |  |
+info: [SelBlocks] branch => @4: [call|returnsValue]
+info: Executing: |call | returnsValue |  |
+info: Executing: |assertEval | "${_result}" === "banana" | true |
+info: script is: "banana" === "banana"
+info: Starting test /selenium-server/tests/StoreAt%20-%20Function%20Scope%20Nesting.html
+info: Executing: |function | storel |  |
+info: [SelBlocks] branch => @9: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.notDefined = null |  |
+info: script is: storedVarsGlobal.notDefined = null
+info: Executing: |assertEval | storedVarsGlobal.notDefined === null | true |
+info: script is: storedVarsGlobal.notDefined === null
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |storeLocal | exists in parent | l |
+info: Executing: |assertEval | storedVars.l === "exists in parent"; | true |
+info: script is: storedVars.l === "exists in parent";
+info: Executing: |call | storel |  |
+info: [SelBlocks] branch => @1: [function|storel]
+info: Executing: |function | storel |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @16: [call|storel]
+info: Executing: |call | storel |  |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Starting test /selenium-server/tests/StoreAt%20-%20While%20Scope%20Nesting.html
+info: Executing: |getEval | storedVarsGlobal.notDefined = null |  |
+info: script is: storedVarsGlobal.notDefined = null
+info: Executing: |assertEval | storedVarsGlobal.notDefined === null | true |
+info: script is: storedVarsGlobal.notDefined === null
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |storeLocal | exists in parent | l |
+info: Executing: |assertEval | storedVars.l === "exists in parent"; | true |
+info: script is: storedVars.l === "exists in parent";
+info: Executing: |storeLocal | 3 | x |
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: [SelBlocks] branch => @17: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |deleteVar | x |  |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Starting test /selenium-server/tests/sendkeys%20keys%20are%20preserved.html
+info: Executing: |assertEval | "KEY_ENTER" in storedVars | true |
+info: script is: "KEY_ENTER" in storedVars
+info: Executing: |assertEval | "KEY_TAB" in storedVars | true |
+info: script is: "KEY_TAB" in storedVars
+info: Executing: |assertEval | "KEY_BACKSPACE" in storedVars | true |
+info: script is: "KEY_BACKSPACE" in storedVars
+
\ No newline at end of file diff --git a/testUserExtension/results-piiexplore.html b/testUserExtension/results-piiexplore.html new file mode 100644 index 0000000..3e9993f --- /dev/null +++ b/testUserExtension/results-piiexplore.html @@ -0,0 +1,8102 @@ + +Test suite results + +

Test suite results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
result:failed
totalTime:38
numTestTotal:58
numTestPasses:56
numTestFailures:2
numCommandPasses:196
numCommandFailures:1
numCommandErrors:1
Selenium Version:2.43
Selenium Revision:.1
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test Suite
README
eval
branching
if-1
if-2
if-3
try - noop
try - finally with no error
try - catch but no error
try - catch specific error
try - catch specific error then finally
try - catch throw finally throw
try - bubble up to catch ALL
try - bubble up to catch ALL via finally
try - bubble up out of noop try to catch specific error
try - bubble up to catch specific error
try - bubble up to catch specific error via finally
try - throw catch rethrow
try - bubble out of nested function calls
try - command bubbling break with finally
try - command bubbling intra try break
try - command bubbling continue with finally
try - command bubbling intra try continue
try - command bubbling error replaced by return
try - command bubbling error replaced by return 2
try - command bubbling return replaced by error
try - exitTest with finally processing
try - try without matching catch
while
for
foreach
foreach-xpath
forjson
forxml
continue-break 1
continue-break 2
continue-break 3
continue-break 4
nested-loops
function
function-recursive
issue-2-function
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
GlobalFunctions
CallGlobalFunction
DefineFunctionParameters - Base
DefineFunctionParameters - With Default Values
StoreLocal - Function Scope
StoreGlobal - Function Scope
StoreGlobal - While Scope
StoreLocal - While Scope
Store - Behaves as StoreLocal
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
+ + +
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
README.html
+ + + + + + + + + + +
README
openhttp://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.htmlPermission denied
+ + +
 
eval.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
eval
resetEmitted
emit"dilbert".isOneOf("dilbert","dogbert","mordac")
emit"bob".isOneOf("dilbert","dogbert","mordac")
emit"red".mapTo("primary", ["red","green","blue"])
emit"orange".mapTo("primary", ["red","green","blue"])
emit"red".translate("e", "E")
emit"red".translate(["red", "green", "blue"], ["blue", "red", "green"])
assertEmitted"true~false~primary~orange~rEd~blue"
+ + +
 
branching.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
branching
resetEmitted
emit"BEFORE"
gotoHERE
emit"A"
labelHERE
gotoIftrueTHERE
emit"B"
labelTHERE
skipNext
emit"C"
emit"AFTER"
assertEmitted"BEFORE~AFTER"
expectError"Target label 'NOWHERE' is not found"
gotoNOWHERE
expectError"Target label 'NOWHERE' is not found"
gotoIftrueNOWHERE
expectError"Requires a number > 1"
skipNext-1
expectError/.*random.* (is not |is un)defined/
skipNextrandom
+ + +
 
if-1.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-1
resetEmitted
emit"BEFORE"
iftrue
emit"truthy"
endIf
iffalse
emit"falsey"
endIf
iftrue
emit"A"
else
emit"B"
endIf
iffalse
emit"X"
else
emit"Y"
endIf
iffalse
emit"false teeth"
else
iftrue
emit"truthF"
else
emit"false false"
endIf
endIf
if"dilbert".isOneOf("dogbert","dilbert","wally")
emit"office mate"
endIf
if"dilbert".isOneOf("ratbert","alice","asok")
emit"mate"
else
emit"coffee mate"
endIf
if"mordac".isOneOf("bob the dinosaur","garbage man","mordac")
emit"cell mate"
else
emit"don't wait"
endIf
emit"AFTER"
assertEmitted"BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER"
+ + +
 
if-2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-2
resetEmitted
iftrue
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-y"
endIf
iffalse
emit"if-y"
elseIftrue
emit"elseIf-a1y"
elseIftrue
emit"else-a2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-b1y"
elseIftrue
emit"elseIf-b2y"
endIf
iffalse
emit"if-y"
elseIffalse
emit"elseIf-y"
else
emit"else-y"
endIf
assertEmitted"if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y"
+ + +
 
if-3.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
if-3
resetEmitted
foreachi2, 0, 1, 4, 3, 5
ifi == 0
emit"if-${i}"
elseIfi == 1
emit"elseIf-${i}"
elseIfi == 2
emit"elseIf-${i}"
elseIfi == 3
emit"elseIf-${i}"
else
emit"else-${i}"
endIf
endForeach
assertEmitted"elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5"
+ + +
 
try - noop.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - noop
log"-- no-op try --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-noop
emit"trying"
endTryt-noop
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + +
 
try - finally with no error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - finally with no error
log"-- try/finally, w/no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-fin
emit"trying"
finally
emit"finally"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~finally~/])"
+ + +
 
try - catch but no error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch but no error
log"-- try/catch, but no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc0
emit"trying"
catch
assertEval"should NEVER enter this catch block due to no error"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + +
 
try - catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error
log"-- catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc1
throw"blamo catch ALL"
assertEval"this command should not be reached, due to thrown"
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~caught 'blamo catch ALL'~/])"
+ + +
 
try - catch specific error then finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error then finally
log"-- catch specific error, then finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel-1
emit"([/"
tryt-spec-inner
emit"trying inner"
throw"blamo inner"
assertEval"this command should not be reached, due to throw"
catch/blamo inner/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-spec-inner
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
endTryt-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])"
+ + +
 
try - catch throw finally throw.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch throw finally throw
log"-- catch/throw, finally/throw --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytcf-trap
assertEvalselblocks.tcf.nestingLevel0
trytcf
emit"trying"
emit"throwing A"
throw"blamoA"
assertEval"this command should not be reached, due to thrown"
catch/blamoA/
emit"caught '" + _error.message + "'"
emit"throwing B"
throw"blamoB"
finally
emit"finally"
emit"throwing C"
throw"blamoC"
endTry
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])"
+ + +
 
try - bubble up to catch ALL.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL
log"-- bubble up to catch ALL --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-all-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-all-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
endTryt-all-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-all-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])"
+ + +
 
try - bubble up to catch ALL via finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL via finally
log"-- bubble up to catch ALL via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-allfin-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-allfin-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-allfin-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-allfin-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])"
+ + +
 
try - bubble up out of noop try to catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up out of noop try to catch specific error
log"-- bubble out of no-op try to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trynoop-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryop-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
endTryop-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrynoop-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])"
+ + +
 
try - bubble up to catch specific error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error
log"-- bubble up to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])"
+ + +
 
try - bubble up to catch specific error via finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error via finally
log"-- bubble up to catch specific error via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])"
+ + +
 
try - throw catch rethrow.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - throw catch rethrow
log"-- throw, catch, rethrow --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryouter
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryinner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing blamo1"
throw"blamo1"
assertEval"this command should not be reached, due to throw"
catch/blamo1/
emit"caught '" + _error.message + "'"
emit"throwing blamo2"
throw"blamo2"
endTryinner
catch/blamo2/
emit"caught '" + _error.message + "'"
endTryouter
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])"
+ + +
 
try - bubble out of nested function calls.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble out of nested function calls
log"-- bubble out of nested function calls --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-invoke
emit"trying"
emit"calling"
callsubBubn = 0
assertEval"this command should not be reached, due error thrown in function"
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-invoke
assertEvalselblocks.tcf.nestingLevel-1
functionsubBubn
trytcf-inner
emit"${n}) trying-inner"
ifn < 2
emit"${n}) calling"
callsubBubn = n+1
else
emit"${n}) throwing"
throw"blamo"
endIf
finally
emit"${n}) finally"
endTrytcf-inner
assertEvalselblocks.tcf.nestingLevel0
endFunction
emit"/])"
assertEmitted"([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])"
+ + +
 
try - command bubbling break with finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling, break with finally
log"-- command bubbling, break w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"${w}) trying"
ifw==2
emit"${w}) BREAK"
break
endIf
finally
emit"${w}) finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])"
+ + +
 
try - command bubbling intra try break.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try break
log"-- command bubbling, intra-try break --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) BREAK"
break
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) BREAK~finallying~/])"
+ + +
 
try - command bubbling continue with finally.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling continue with finally
log"-- command bubbling, continue w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"${w}) trying"
ifw==2
emit"${w}) CONTINUE"
continue
endIf
finally
emit"${w}) finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])"
+ + +
 
try - command bubbling intra try continue.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try continue
log"-- command bubbling, intra-try continue --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) CONTINUE"
continue
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])"
+ + +
 
try - command bubbling error replaced by return.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubA
emit"returned ${_result}"
functioncmdBubA
emit"in cmdBubA"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to return/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])"
+ + +
 
try - command bubbling error replaced by return 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return 2
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubB
emit"returned ${_result}"
functioncmdBubB
emit"in cmdBubB"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"throwing"
throw"short-lived error"
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to throw/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])"
+ + +
 
try - command bubbling return replaced by error.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling return replaced by error
log"-- command bubbling, return replaced by error --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubC
emit"returned ${_result}"
functioncmdBubC
emit"in cmdBubC"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf-guardrail
assertEvalselblocks.tcf.nestingLevel0
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"throwing"
throw"this-error-replaces-return-1"
endTry
catch/this-error-replaces-return-1/
emit"caught '" + _error.message + "'"
assertEvalselblocks.tcf.nestingLevel0
endTry
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])"
+ + +
 
try - exitTest with finally processing.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - exitTest with finally processing
log"-- exitTest w/finally processing --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryabort
emit"trying"
emit"exitTest ..."
exitTest
finally
emit"finallying"
assertEmitted"([/~trying~exitTest ...~finallying"
resetEmitted
endTryabort
assertEval"this command should not be reached, due to exitTest above"
+ + +
 
try - try without matching catch.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - try without matching catch
log"-- try without matching catch --"
resetEmitted
assertEvalselblocks.tcf.nestingLevel-1
trymiss
assertEvaltruetrue
throw"blamo will NOT be caught at all"
assertEval"this command should not be reached"
catch/will NOT catch it/
log"caught miss '" + _error.message + "'"
finally
log"finally"
endTrymissCommand execution failure. Please search the user group at https://groups.google.com/forum/#!forum/selenium-users for error details from the log window.  The error message is: blamo will NOT be caught at all
assertEvalselblocks.tcf.nestingLevel-1
emit"trying"
+ + +
 
while.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsw
store3w
emit"START: ${w}"
whilew == 42
emit"SHOULD NEVER HAPPEN"
endWhile
whilew > 0
emit"iter=${w}"
storeEval${w}-1w
endWhile
emit"END: ${w}"
assertEmitted"START: 3~iter=3~iter=2~iter=1~END: 3"
+ + +
 
for.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsf
emit"START ${f}"
fors=0,f=3; f <= 5; f++
emit"iter=${f}.${s}"
endFor
emit"END ${f}"
assertEmitted"START $" + "{f}~iter=3.0~iter=4.0~iter=5.0~END $" + "{f}"
+ + +
 
foreach.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVars_i, fe
emit"START ${_i}-${fe}"
foreachfe"dilbert", "dogbert", "wally"
emit"${_i}) ${fe}"
endForeach
emit"END ${_i}-${fe}"
assertEmitted"START $" + "{_i}-$" + "{fe}~0) dilbert~1) dogbert~2) wally~END $" + "{_i}-$" + "{fe}"
+ + +
 
foreach-xpath.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreachX
resetEmitted
echo$x("//input")$x("//input")
echo$X("//input")$X("//input")
echobeginbegin
emit"START ${_i}) ${link}"
foreachlink$X("//input")
emit"${_i}) ${link}"
echo${link}[object HTMLInputElement]
endForeach
emit"END ${_i}) ${link}"
assertEmitted"START ${" + "_i}) ${" + "link}~0) [object HTMLInputElement]~1) [object HTMLInputElement]~2) [object HTMLInputElement]~END ${" + "_i}) ${" + "link}"
+ + +
 
forjson.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
ifglobalContext.onServer === true
store../data/forjson.jsonforJsonFileName
else
storedata/forjson.jsonforJsonFileName
endIf
resetEmitted
deleteVarsjname
emit"START ${jname}"
forJson${forJsonFileName}
emitjname
endForJson
emit"INTERMISSION ${jname}"
loadJsonVars${forJsonFileName}jname == "dogbert"
emit"END ${jname}"
assertEmitted"START $" + "{jname}~dilbert~dogbert~wally~INTERMISSION $" + "{jname}~END dogbert"
expectError"Requires a JSON file path or URL"
loadJsonVars
expectError"Multiple JSON objects are not valid for this command"
loadJsonVars${forJsonFileName}
expectError'"flubber" is not a boolean expression'
loadJsonVars${forJsonFileName}"flubber"
+ + +
 
forxml.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
resetEmitted
deleteVarsxname
emit"START ${xname}"
forXml${forXmlFileName}
emitxname
endForXml
emit"INTERMISSION ${xname}"
loadXmlVars${forXmlFileName}xname == "dogbert"
emit"END ${xname}"
assertEmitted"START $" + "{xname}~dilbert~dogbert~wally~INTERMISSION $" + "{xname}~END dogbert"
loadXmlVars${forXmlFileName}xname == "dogbert"
expectError"Requires an XML file path or URL"
loadXmlVars
expectError"Multiple XML elements are not valid for this command"
loadXmlVars${forXmlFileName}
expectError'"flubber" is not a boolean expression'
loadXmlVars${forXmlFileName}"flubber"
+ + +
 
continue-break 1.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 1
resetEmitted
deleteVarsf
forf=3; f <= 9; f++
continuef == 6
iff > 6
iff == 7
continue
else
break
endIf
endIf
emit"iter=${f}"
endFor
assertEmitted"iter=3~iter=4~iter=5"
+ + +
 
continue-break 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 2
resetEmitted
store0i
whilei++ < 10
continuei==3
breaki==5
emit"iter=${i}"
endWhile
assertEmitted"iter=1~iter=2~iter=4"
+ + +
 
continue-break 3.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 3
resetEmitted
foreachfe"dilbert","dogbert","wally"
continuefe=="dogbert"
breakfe=="wally"
emit"iter=${fe}"
endForeach
assertEmitted"iter=dilbert"
+ + +
 
continue-break 4.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 4
resetEmitted
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
forXml${forXmlFileName}
continuexname=="dogbert"
breakxname=="wally"
emit"iter=${xname}"
endForXml
assertEmitted"iter=dilbert"
+ + +
 
nested-loops.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVarsi, n, uname
startTimer
store2i
emit"START ${i}"
whilei > 0
emit"while=${i}"
foreachuname"dilbert", "dogbert"
emit"foreach=${uname}"
forn = 2; n <=3; n++
emit"FOR=${n}"
forn = 7; n <= 8; n++
emit"for=${n}"
endFor
endFor
emit"endFor ${n}"
endForeach
storeEval${i}-1i
endWhile
emit"END ${i}"
timerElapsed
assertEmitted"START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2"
+ + +
 
function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
subtest
deleteVarssname, srole
assertEval"START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}"true
calldoSomethingsname = "dilbert,Q", srole = "goof"
assertEval"${_result}" === "sname=dilbert,Q,srole=goof"true
deleteVarssname, srole
functiondoSomethingsname
return"sname=${sname},srole=${srole}"
endFunctiondoSomething
deleteVarssname, srole
calldoSomethingsname = "dogbert", srole = "woof"
assertEval"${_result}" === "sname=dogbert,srole=woof"true
deleteVarssname, srole
calldoSomethingsname = "ratbert", srole = "squeak"
assertEval"${_result}" === "sname=ratbert,srole=squeak"true
deleteVarssname, srole
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
assertEval"${_result}" === "sname=${sname},srole=super=user"true
deleteVarssname, srole
endForeach
assertEval"DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}"true
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
deleteVarssname, srole
scriptdoDeprecatedsname
return"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEval"${_result}" === "sname=wally,srole=lazy"true
deleteVarssname, srole
+ + +
 
function-recursive.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
factorial
resetEmitted
deleteVarsdegree, n, _result, ud
store7degree
startTimerfactorial ${degree}
callfacn=degree
timerElapsed
emitdegree + "!=" + _result
functionfacn
ifn <= 1
return1
else
callfacn = n-1
emit_result
returnn * _result
endIf
endFunction
functionuno
emit"UNO"
storeEval${ud}-1ud
ifud > 0
calldue
endIf
endFunctionuno
functiondue
emit"DUE"
storeEval${ud}-1ud
ifud > 0
calluno
endIf
endFunctiondue
store5ud
calluno
assertEmitted"1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO"
+ + +
 
issue-2-function.html
+ + + + + + + + + + + + + + + + + + + + + + + + +
issue#2
functionxyz
log'here'
endFunction
callxyz
+ + +
 
exitTest - base case.html
+ + + + + + + + + + + + + + + + + + + + +
exitTest - base case
resetEmitted
exitTest
throw"shouldn't happen"
+ + +
 
exitTest - from within a loop.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a loop
fori=0; i < 5; i++
ifi == 3
exitTest
endIf
ifi === 3
throw"This test should exit when the increment gets to 3, and this should never be thrown."
endIf
endFor
+ + +
 
exitTest - from within a function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a function
calldoSubExit
throw"shouldn't happen"
functiondoSubExit
exitTest
endFunctiondoSubExit
+ + +
 
GlobalFunctions.html
+ + + + + + + + + + + + + + + + + + + + + + + + +
functions
getEvalglobalStoredVars = {};
functionsetGlobalVar
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
+ + +
 
CallGlobalFunction.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + +
 
DefineFunctionParameters - Base.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - Base
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionbobx,y
assertEval"${x}" === "overwritten"true
assertEvalstoredVars.y === undefinedtrue
endFunction
callbobx="overwritten"
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEvalstoredVars.y === undefinedfalse
assertEval"${y}" === "original";true
+ + +
 
DefineFunctionParameters - With Default Values.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - With Default Values
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionleakTestx="fn default x",y="fn default y"
storeoverwrittenx
storeoverwritteny
endFunction
functiondefaultsTestx="fn default x",y="fn default y"
assertEval${x} === "fn default x"true
store"overwritten"x
assertEval${x} === "overwritten"true
assertEval${y} === "fn default y"true
store"overwritten"y
assertEval${y} === "overwritten"true
endFunction
calldefaultsTest
callleakTest
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTesty = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten", y = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
+ + +
 
StoreLocal - Function Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
StoreGlobal - Function Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - Function Scope
functionblockScopeVars
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endFunction
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + +
 
StoreGlobal - While Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - While Scope
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
store1i
whilei > 0
store0i
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endWhile
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + +
 
StoreLocal - While Scope.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - While Scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
store1i
whilei > 0
store0i
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endWhile
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
Store - Behaves as StoreLocal.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store - Behaves as StoreLocal
functionblockScopeVars
storethis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + +
 
Function - Can Return Value.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Function - Can Return Value
functionreturnsValue
return"banana"
endFunction
callreturnsValue
assertEval"${_result}" === "banana"true
+ + +
 
StoreAt - Function Scope Nesting.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - Function Scope Nesting
functionstorel
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
endFunction
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
callstorel
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + +
 
StoreAt - While Scope Nesting.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - While Scope Nesting
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
storeLocal3x
whilex !== 0
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
storeEvalLocalx -= 1
endWhile
deleteVarx
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + +
 
sendkeys keys are preserved.html
+ + + + + + + + + + + + + + + + + + + + +
sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ + +
 
+info: Starting test /selenium-server/tests/README.html
+info: Executing: |open | http://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.html |  |
+error: isNewPageLoaded found an old pageLoadError: Error: Permission denied
+warn: currentTest.recordFailure: Permission denied
+info: Starting test /selenium-server/tests/eval.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "dilbert".isOneOf("dilbert","dogbert","mordac") |  |
+info: Executing: |emit | "bob".isOneOf("dilbert","dogbert","mordac") |  |
+info: Executing: |emit | "red".mapTo("primary", ["red","green","blue"]) |  |
+info: Executing: |emit | "orange".mapTo("primary", ["red","green","blue"]) |  |
+info: Executing: |emit | "red".translate("e", "E") |  |
+info: Executing: |emit | "red".translate(["red", "green", "blue"], ["blue", "red", "green"]) |  |
+info: Executing: |assertEmitted | "true~false~primary~orange~rEd~blue" |  |
+info: Starting test /selenium-server/tests/branching.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "BEFORE" |  |
+info: Executing: |goto | HERE |  |
+info: [SelBlocks] branch => @5: [label|HERE]
+info: Executing: |label | HERE |  |
+info: Executing: |gotoIf | true | THERE |
+info: [SelBlocks] branch => @8: [label|THERE]
+info: Executing: |label | THERE |  |
+info: Executing: |skipNext |  |  |
+info: [SelBlocks] branch => @11: [emit|"AFTER"]
+info: Executing: |emit | "AFTER" |  |
+info: Executing: |assertEmitted | "BEFORE~AFTER" |  |
+info: Executing: |expectError | "Target label 'NOWHERE' is not found" |  |
+info: Executing: |goto | NOWHERE |  |
+error: [SelBlocks] Error @14: [goto|NOWHERE] Target label 'NOWHERE' is not found.
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |expectError | "Target label 'NOWHERE' is not found" |  |
+info: Executing: |gotoIf | true | NOWHERE |
+error: [SelBlocks] Error @16: [gotoIf|true|NOWHERE] Target label 'NOWHERE' is not found.
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |expectError | "Requires a number > 1" |  |
+info: Executing: |skipNext | -1 |  |
+error: [SelBlocks] Error @18: [skipNext|-1] Requires a number > 1
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |expectError | /.*random.* (is not |is un)defined/ |  |
+info: Executing: |skipNext | random |  |
+error: [SelBlocks] Error  While evaluating Javascript expression: random
+warn: [SelBlocks] __Stack Trace__
+info: Starting test /selenium-server/tests/if-1.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "BEFORE" |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "truthy" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @8: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "A" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @16: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "Y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @21: [else]
+info: Executing: |else |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "truthF" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @26: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "dilbert".isOneOf("dogbert","dilbert","wally") |  |
+info: Executing: |emit | "office mate" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "dilbert".isOneOf("ratbert","alice","asok") |  |
+info: [SelBlocks] branch => @33: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "coffee mate" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | "mordac".isOneOf("bob the dinosaur","garbage man","mordac") |  |
+info: Executing: |emit | "cell mate" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @40: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "AFTER" |  |
+info: Executing: |assertEmitted | "BEFORE~truthy~A~Y~truthF~office mate~coffee mate~cell mate~AFTER" |  |
+info: Starting test /selenium-server/tests/if-2.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |if | true |  |
+info: Executing: |emit | "if-y" |  |
+info: Executing: |elseIf | true |  |
+info: [SelBlocks] branch => @6: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @9: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @14: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-a1y" |  |
+info: Executing: |elseIf | true |  |
+info: [SelBlocks] branch => @18: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @21: [elseIf|false]
+info: Executing: |elseIf | false |  |
+info: [SelBlocks] branch => @23: [elseIf|true]
+info: Executing: |elseIf | true |  |
+info: Executing: |emit | "elseIf-b2y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |if | false |  |
+info: [SelBlocks] branch => @28: [elseIf|false]
+info: Executing: |elseIf | false |  |
+info: [SelBlocks] branch => @30: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-y" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |assertEmitted | "if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y" |  |
+info: Starting test /selenium-server/tests/if-3.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: Executing: |emit | "if-${i}" |  |
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-${i}" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: Executing: |emit | "elseIf-${i}" |  |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @13: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: Executing: |if | i == 0 |  |
+info: [SelBlocks] branch => @5: [elseIf|i == 1]
+info: Executing: |elseIf | i == 1 |  |
+info: [SelBlocks] branch => @7: [elseIf|i == 2]
+info: Executing: |elseIf | i == 2 |  |
+info: [SelBlocks] branch => @9: [elseIf|i == 3]
+info: Executing: |elseIf | i == 3 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "else-${i}" |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|i|2, 0, 1, 4, 3, 5]
+info: Executing: |foreach | i | 2, 0, 1, 4, 3, 5 |
+info: [SelBlocks] branch => @14: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEmitted | "elseIf-2~if-0~elseIf-1~else-4~elseIf-3~else-5" |  |
+info: Starting test /selenium-server/tests/try%20-%20noop.html
+info: Executing: |log | "-- no-op try --" |  |
+info: [SelBench] -- no-op try --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-noop |  |
+warn: [SelBlocks] @5: [try|t-noop] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying" |  |
+info: Executing: |endTry | t-noop |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20finally%20with%20no%20error.html
+info: Executing: |log | "-- try/finally, w/no error --" |  |
+info: [SelBench] -- try/finally, w/no error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-fin |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20but%20no%20error.html
+info: Executing: |log | "-- try/catch, but no error --" |  |
+info: [SelBench] -- try/catch, but no error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tc0 |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |catch |  |  |
+info: [SelBlocks] branch => @9: [endTry]
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20specific%20error.html
+info: Executing: |log | "-- catch specific error --" |  |
+info: [SelBench] -- catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tc1 |  |
+info: Executing: |throw | "blamo catch ALL" |  |
+info: [SelBlocks] @6, error has been caught :: 
+info: [SelBlocks] branch => @8: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~caught 'blamo catch ALL'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20specific%20error%20then%20finally.html
+info: Executing: |log | "-- catch specific error, then finally --" |  |
+info: [SelBench] -- catch specific error, then finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-spec-outer |  |
+warn: [SelBlocks] @5: [try|t-spec-outer] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "([/" |  |
+info: Executing: |try | t-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |throw | "blamo inner" |  |
+info: [SelBlocks] @11, error has been caught :: /blamo inner/
+info: [SelBlocks] branch => @13: [catch|/blamo inner/]
+info: Executing: |catch | /blamo inner/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | t-spec-inner |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |endTry | t-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20catch%20throw%20finally%20throw.html
+info: Executing: |log | "-- catch/throw, finally/throw --" |  |
+info: [SelBench] -- catch/throw, finally/throw --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tcf-trap |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "throwing A" |  |
+info: Executing: |throw | "blamoA" |  |
+info: [SelBlocks] @10, error has been caught :: /blamoA/
+info: [SelBlocks] branch => @12: [catch|/blamoA/]
+info: Executing: |catch | /blamoA/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |emit | "throwing B" |  |
+info: Executing: |throw | "blamoB" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @16: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |emit | "throwing C" |  |
+info: Executing: |throw | "blamoC" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @20: [endTry]
+info: Executing: |endTry |  |  |
+info: [SelBlocks] @20, error has been caught :: @19 
+info: [SelBlocks] branch => @22: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20ALL.html
+info: Executing: |log | "-- bubble up to catch ALL --" |  |
+info: [SelBench] -- bubble up to catch ALL --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-all-outer |  |
+info: Executing: |emit | "trying-outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-all-inner |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |throw | "blamo try-catch-finally" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @14: [endTry|t-all-inner]
+info: Executing: |endTry | t-all-inner |  |
+info: [SelBlocks] @14, error has been caught :: @10 
+info: [SelBlocks] branch => @16: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught-outer '" + _error.message + "'" |  |
+info: Executing: |endTry | t-all-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20ALL%20via%20finally.html
+info: Executing: |log | "-- bubble up to catch ALL via finally --" |  |
+info: [SelBench] -- bubble up to catch ALL via finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-allfin-outer |  |
+info: Executing: |emit | "trying-outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | t-allfin-inner |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |throw | "blamo try-catch-finally" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | t-allfin-inner |  |
+info: [SelBlocks] @16, error has been caught :: @10 
+info: [SelBlocks] branch => @18: [catch]
+info: Executing: |catch |  |  |
+info: Executing: |emit | "caught-outer '" + _error.message + "'" |  |
+info: Executing: |endTry | t-allfin-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20out%20of%20noop%20try%20to%20catch%20specific%20error.html
+info: Executing: |log | "-- bubble out of no-op try to catch specific error --" |  |
+info: [SelBench] -- bubble out of no-op try to catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | noop-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | op-inner |  |
+warn: [SelBlocks] @8: [try|op-inner] does not have a catch-block nor a finally-block, and therefore serves no purpose
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @14: [endTry|op-inner]
+info: Executing: |endTry | op-inner |  |
+info: [SelBlocks] @14, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @15: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | noop-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20specific%20error.html
+info: Executing: |log | "-- bubble up to catch specific error --" |  |
+info: [SelBench] -- bubble up to catch specific error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-inner |  |
+info: [SelBlocks] @16, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @17: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry | bub-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20up%20to%20catch%20specific%20error%20via%20finally.html
+info: Executing: |log | "-- bubble up to catch specific error via finally --" |  |
+info: [SelBench] -- bubble up to catch specific error via finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-spec-inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing inner" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-inner |  |
+info: [SelBlocks] @16, error has been caught :: @12 /blamo/
+info: [SelBlocks] branch => @17: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-spec-outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20throw%20catch%20rethrow.html
+info: Executing: |log | "-- throw, catch, rethrow --" |  |
+info: [SelBench] -- throw, catch, rethrow --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | outer |  |
+info: Executing: |emit | "trying outer" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | inner |  |
+info: Executing: |emit | "trying inner" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "throwing blamo1" |  |
+info: Executing: |throw | "blamo1" |  |
+info: [SelBlocks] @12, error has been caught :: /blamo1/
+info: [SelBlocks] branch => @14: [catch|/blamo1/]
+info: Executing: |catch | /blamo1/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |emit | "throwing blamo2" |  |
+info: Executing: |throw | "blamo2" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @18: [endTry|inner]
+info: Executing: |endTry | inner |  |
+info: [SelBlocks] @18, error has been caught :: @17 /blamo2/
+info: [SelBlocks] branch => @19: [catch|/blamo2/]
+info: Executing: |catch | /blamo2/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |endTry | outer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20bubble%20out%20of%20nested%20function%20calls.html
+info: Executing: |log | "-- bubble out of nested function calls --" |  |
+info: [SelBench] -- bubble out of nested function calls --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | bub-invoke |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | subBub | n = 0 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: Executing: |emit | "${n}) calling" |  |
+info: Executing: |call | subBub | n = n+1 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: Executing: |emit | "${n}) calling" |  |
+info: Executing: |call | subBub | n = n+1 |
+info: [SelBlocks] branch => @16: [function|subBub|n]
+info: Executing: |function | subBub | n |
+info: Executing: |try | tcf-inner |  |
+info: Executing: |emit | "${n}) trying-inner" |  |
+info: Executing: |if | n < 2 |  |
+info: [SelBlocks] branch => @22: [else]
+info: Executing: |else |  |  |
+info: Executing: |emit | "${n}) throwing" |  |
+info: Executing: |throw | "blamo" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @26: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${n}) finally" |  |
+info: Executing: |endTry | tcf-inner |  |
+info: [SelBlocks] function 'subBub' aborting due to error
+info: [SelBlocks] @28, error has been caught :: @28 /blamo/
+info: [SelBlocks] branch => @10: [catch|/blamo/]
+info: Executing: |catch | /blamo/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finally" |  |
+info: Executing: |endTry | bub-invoke |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |function | subBub | n |
+info: [SelBlocks] branch => @30: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20break%20with%20finally.html
+info: Executing: |log | "-- command bubbling, break w/finally --" |  |
+info: [SelBench] -- command bubbling, break w/finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) BREAK" |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] Command @11: [break], suspended while finally block runs
+info: [SelBlocks] branch => @13: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @11: [break]
+info: [SelBlocks] branch => @11: [break]
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @18: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20intra%20try%20break.html
+info: Executing: |log | "-- command bubbling, intra-try break --" |  |
+info: [SelBench] -- command bubbling, intra-try break --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | breaker |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) BREAK" |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |endTry | breaker |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~while'g~3) iterating~2) BREAK~finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20continue%20with%20finally.html
+info: Executing: |log | "-- command bubbling, continue w/finally --" |  |
+info: [SelBench] -- command bubbling, continue w/finally --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) CONTINUE" |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] Command @11: [continue], suspended while finally block runs
+info: [SelBlocks] branch => @13: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @11: [continue]
+info: [SelBlocks] branch => @11: [continue]
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "${w}) trying" |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "${w}) finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @5: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: [SelBlocks] branch => @18: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20intra%20try%20continue.html
+info: Executing: |log | "-- command bubbling, intra-try continue --" |  |
+info: [SelBench] -- command bubbling, intra-try continue --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | continuer |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "while'g" |  |
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: Executing: |emit | "${w}) CONTINUE" |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: Executing: |if | w==2 |  |
+info: [SelBlocks] branch => @12: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "${w}) iterating" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @8: [for|w=3; w > 0; w--]
+info: Executing: |for | w=3; w > 0; w-- |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |endTry | continuer |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20error%20replaced%20by%20return.html
+info: Executing: |log | "-- command bubbling, error replaced by return --" |  |
+info: [SelBench] -- command bubbling, error replaced by return --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubA |  |
+info: [SelBlocks] branch => @7: [function|cmdBubA]
+info: Executing: |function | cmdBubA |  |
+info: Executing: |emit | "in cmdBubA" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "returning (1)" |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] Command @13: [return|1], suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "returning (2)" |  |
+info: Executing: |return | 2 |  |
+info: Executing: |endTry |  |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @17: [return|2]
+info: [SelBlocks] branch => @17: [return|2]
+info: Executing: |return | 2 |  |
+info: [SelBlocks] branch => @5: [call|cmdBubA]
+info: Executing: |call | cmdBubA |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubA |  |
+info: [SelBlocks] branch => @20: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20error%20replaced%20by%20return%202.html
+info: Executing: |log | "-- command bubbling, error replaced by return --" |  |
+info: [SelBench] -- command bubbling, error replaced by return --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubB |  |
+info: [SelBlocks] branch => @7: [function|cmdBubB]
+info: Executing: |function | cmdBubB |  |
+info: Executing: |emit | "in cmdBubB" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "throwing" |  |
+info: Executing: |throw | "short-lived error" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @14: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "returning (2)" |  |
+info: Executing: |return | 2 |  |
+info: Executing: |endTry |  |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @17: [return|2]
+info: [SelBlocks] branch => @17: [return|2]
+info: Executing: |return | 2 |  |
+info: [SelBlocks] branch => @5: [call|cmdBubB]
+info: Executing: |call | cmdBubB |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubB |  |
+info: [SelBlocks] branch => @20: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20command%20bubbling%20return%20replaced%20by%20error.html
+info: Executing: |log | "-- command bubbling, return replaced by error --" |  |
+info: [SelBench] -- command bubbling, return replaced by error --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |emit | "calling" |  |
+info: Executing: |call | cmdBubC |  |
+info: [SelBlocks] branch => @7: [function|cmdBubC]
+info: Executing: |function | cmdBubC |  |
+info: Executing: |emit | "in cmdBubC" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf-guardrail |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | cmdBub-tcf |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "returning (1)" |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] Command @15: [return|1], suspended while finally block runs
+info: [SelBlocks] branch => @16: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |emit | "throwing" |  |
+info: Executing: |throw | "this-error-replaces-return-1" |  |
+info: [SelBlocks] No further handling, error bubbling will continue outside of this try.
+info: [SelBlocks] branch => @20: [endTry]
+info: Executing: |endTry |  |  |
+info: [SelBlocks] @20, error has been caught :: @19 /this-error-replaces-return-1/
+info: [SelBlocks] branch => @21: [catch|/this-error-replaces-return-1/]
+info: Executing: |catch | /this-error-replaces-return-1/ |  |
+info: Executing: |emit | "caught '" + _error.message + "'" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | 0 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |endTry |  |  |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @5: [call|cmdBubC]
+info: Executing: |call | cmdBubC |  |
+info: Executing: |emit | "returned ${_result}" |  |
+info: Executing: |function | cmdBubC |  |
+info: [SelBlocks] branch => @25: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |emit | "/])" |  |
+info: Executing: |assertEmitted | "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])" |  |
+info: Starting test /selenium-server/tests/try%20-%20exitTest%20with%20finally%20processing.html
+info: Executing: |log | "-- exitTest w/finally processing --" |  |
+info: [SelBench] -- exitTest w/finally processing --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |emit | "([/" |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | abort |  |
+info: Executing: |emit | "trying" |  |
+info: Executing: |emit | "exitTest ..." |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] Command @8: [exitTest], suspended while finally block runs
+info: [SelBlocks] branch => @9: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |emit | "finallying" |  |
+info: Executing: |assertEmitted | "([/~trying~exitTest ...~finallying" |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |endTry | abort |  |
+info: [SelBlocks] command-bubbling complete - suspended command executing now @8: [exitTest]
+info: [SelBlocks] branch => @8: [exitTest]
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/try%20-%20try%20without%20matching%20catch.html
+info: Executing: |log | "-- try without matching catch --" |  |
+info: [SelBench] -- try without matching catch --
+info: Executing: |resetEmitted |  |  |
+info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 |
+info: script is: selblocks.tcf.nestingLevel
+info: Executing: |try | miss |  |
+info: Executing: |assertEval | true | true |
+info: script is: true
+info: Executing: |throw | "blamo will NOT be caught at all" |  |
+info: [SelBlocks] Bubbling suspended while finally block runs
+info: [SelBlocks] branch => @10: [finally]
+info: Executing: |finally |  |  |
+info: Executing: |log | "finally" |  |
+info: [SelBench] finally
+info: Executing: |endTry | miss |  |
+error: [SelBlocks] Error was not caught: 'blamo will NOT be caught at all'
+error: Unexpected Exception: blamo will NOT be caught at all
+error: Exception details: name -> SelblocksError, message -> blamo will NOT be caught at all, idx -> 5, stack -> SelblocksError: blamo will NOT be caught at all
+   at Selenium.prototype.doThrow (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2003:5)
+   at retval (http://htmlpreview.github.io/selenium-server/core/scripts/htmlutils.js:60:5)
+   at ActionHandler.prototype.execute (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-commandhandlers.js:314:5)
+   at TestLoop.prototype._executeCurrentCommand (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:112:9)
+   at $$.handleAsTryBlock (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:1091:7)
+   at retval (http://htmlpreview.github.io/selenium-server/core/scripts/htmlutils.js:60:5)
+warn: currentTest.recordFailure: Command execution failure. Please search the user group at https://groups.google.com/forum/#!forum/selenium-users for error details from the log window.  The error message is: blamo will NOT be caught at all
+info: Starting test /selenium-server/tests/while.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | w |  |
+info: Executing: |store | 3 | w |
+info: Executing: |emit | "START: ${w}" |  |
+info: Executing: |while | w == 42 |  |
+info: [SelBlocks] branch => @7: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 3-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 2-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: Executing: |emit | "iter=${w}" |  |
+info: Executing: |storeEval | ${w}-1 | w |
+info: script is: 1-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|w > 0]
+info: Executing: |while | w > 0 |  |
+info: [SelBlocks] branch => @11: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |emit | "END: ${w}" |  |
+info: Executing: |assertEmitted | "START: 3~iter=3~iter=2~iter=1~END: 3" |  |
+info: Starting test /selenium-server/tests/for.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | f |  |
+info: Executing: |emit | "START ${f}" |  |
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: Executing: |emit | "iter=${f}.${s}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @4: [for|s=0,f=3; f <= 5; f++]
+info: Executing: |for | s=0,f=3; f <= 5; f++ |  |
+info: [SelBlocks] branch => @6: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "END ${f}" |  |
+info: Executing: |assertEmitted | "START $" + "{f}~iter=3.0~iter=4.0~iter=5.0~END $" + "{f}" |  |
+info: Starting test /selenium-server/tests/foreach.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | _i, fe |  |
+info: Executing: |emit | "START ${_i}-${fe}" |  |
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: Executing: |emit | "${_i}) ${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @4: [foreach|fe|"dilbert", "dogbert", "wally"]
+info: Executing: |foreach | fe | "dilbert", "dogbert", "wally" |
+info: [SelBlocks] branch => @6: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "END ${_i}-${fe}" |  |
+info: Executing: |assertEmitted | "START $" + "{_i}-$" + "{fe}~0) dilbert~1) dogbert~2) wally~END $" + "{_i}-$" + "{fe}" |  |
+info: Starting test /selenium-server/tests/foreach-xpath.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |echo | $x("//input") |  |
+info: Executing: |echo | $X("//input") |  |
+info: Executing: |echo | begin |  |
+info: Executing: |emit | "START ${_i}) ${link}" |  |
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} | [object HTMLInputElement] |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: Executing: |emit | "${_i}) ${link}" |  |
+info: Executing: |echo | ${link} | [object HTMLInputElement] |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @6: [foreach|link|$X("//input")]
+info: Executing: |foreach | link | $X("//input") |
+info: [SelBlocks] branch => @9: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "END ${_i}) ${link}" |  |
+info: Executing: |assertEmitted | "START ${" + "_i}) ${" + "link}~0) [object HTMLInputElement]~1) [object HTMLInputElement]~2) [object HTMLInputElement]~END ${" + "_i}) ${" + "link}" |  |
+info: Starting test /selenium-server/tests/forjson.html
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forjson.json | forJsonFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @5: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | jname |  |
+info: Executing: |emit | "START ${jname}" |  |
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: [SelBlocks] Reading from: ../data/forjson.json
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: Executing: |emit | jname |  |
+info: Executing: |endForJson |  |  |
+info: [SelBlocks] branch => @9: [forJson|${forJsonFileName}]
+info: Executing: |forJson | ${forJsonFileName} |  |
+info: [SelBlocks] branch => @11: [endForJson]
+info: Executing: |endForJson |  |  |
+info: Executing: |emit | "INTERMISSION ${jname}" |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} | jname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forjson.json
+info: Executing: |emit | "END ${jname}" |  |
+info: Executing: |assertEmitted | "START $" + "{jname}~dilbert~dogbert~wally~INTERMISSION $" + "{jname}~END dogbert" |  |
+info: Executing: |expectError | "Requires a JSON file path or URL" |  |
+info: Executing: |loadJsonVars |  |  |
+error: [SelBlocks] Error @17: [loadJsonVars] Requires a JSON file path or URL.
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |expectError | "Multiple JSON objects are not valid for this command" |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} |  |
+info: [SelBlocks] Reading from: ../data/forjson.json
+error: [SelBlocks] Error @19: [loadJsonVars|${forJsonFileName}] Multiple JSON objects are not valid for this command. (A specific JSON object can be selected by specifying: name="value".)
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |expectError | '"flubber" is not a boolean expression' |  |
+info: Executing: |loadJsonVars | ${forJsonFileName} | "flubber" |
+info: [SelBlocks] Reading from: ../data/forjson.json
+error: [SelBlocks] Error @21: [loadJsonVars|${forJsonFileName}|"flubber"], "flubber" is not a boolean expression
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Starting test /selenium-server/tests/forxml.html
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forxml.xml | forXmlFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @5: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | xname |  |
+info: Executing: |emit | "START ${xname}" |  |
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |emit | xname |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @9: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] branch => @11: [endForXml]
+info: Executing: |endForXml |  |  |
+info: Executing: |emit | "INTERMISSION ${xname}" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | xname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |emit | "END ${xname}" |  |
+info: Executing: |assertEmitted | "START $" + "{xname}~dilbert~dogbert~wally~INTERMISSION $" + "{xname}~END dogbert" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | xname == "dogbert" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |expectError | "Requires an XML file path or URL" |  |
+info: Executing: |loadXmlVars |  |  |
+error: [SelBlocks] Error @18: [loadXmlVars] Requires an XML file path or URL.
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |expectError | "Multiple XML elements are not valid for this command" |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+error: [SelBlocks] Error @20: [loadXmlVars|${forXmlFileName}] Multiple XML elements are not valid for this command. (A specific XML element can be selected by specifying: name="value".)
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |expectError | '"flubber" is not a boolean expression' |  |
+info: Executing: |loadXmlVars | ${forXmlFileName} | "flubber" |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+error: [SelBlocks] Error @22: [loadXmlVars|${forXmlFileName}|"flubber"], "flubber" is not a boolean expression
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Starting test /selenium-server/tests/continue-break%201.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | f |  |
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: [SelBlocks] branch => @11: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |emit | "iter=${f}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: Executing: |if | f == 7 |  |
+info: Executing: |continue |  |  |
+info: [SelBlocks] branch => @3: [for|f=3; f <= 9; f++]
+info: Executing: |for | f=3; f <= 9; f++ |  |
+info: Executing: |continue | f == 6 |  |
+info: Executing: |if | f > 6 |  |
+info: Executing: |if | f == 7 |  |
+info: [SelBlocks] branch => @8: [else]
+info: Executing: |else |  |  |
+info: Executing: |break |  |  |
+info: [SelBlocks] branch => @13: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |assertEmitted | "iter=3~iter=4~iter=5" |  |
+info: Starting test /selenium-server/tests/continue-break%202.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |store | 0 | i |
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: Executing: |emit | "iter=${i}" |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @3: [while|i++ < 10]
+info: Executing: |while | i++ < 10 |  |
+info: Executing: |continue | i==3 |  |
+info: Executing: |break | i==5 |  |
+info: [SelBlocks] branch => @7: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEmitted | "iter=1~iter=2~iter=4" |  |
+info: Starting test /selenium-server/tests/continue-break%203.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: Executing: |break | fe=="wally" |  |
+info: Executing: |emit | "iter=${fe}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @2: [foreach|fe|"dilbert","dogbert","wally"]
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: [SelBlocks] branch => @2: [foreach|fe|"dilbert","dogbert","wally"]
+info: Executing: |foreach | fe | "dilbert","dogbert","wally" |
+info: Executing: |continue | fe=="dogbert" |  |
+info: Executing: |break | fe=="wally" |  |
+info: [SelBlocks] branch => @6: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEmitted | "iter=dilbert" |  |
+info: Starting test /selenium-server/tests/continue-break%204.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |if | globalContext.onServer === true |  |
+info: Executing: |store | ../data/forxml.xml | forXmlFileName |
+info: Executing: |else |  |  |
+info: [SelBlocks] branch => @6: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: [SelBlocks] Reading from: ../data/forxml.xml
+info: Executing: |continue | xname=="dogbert" |  |
+info: Executing: |break | xname=="wally" |  |
+info: Executing: |emit | "iter=${xname}" |  |
+info: Executing: |endForXml |  |  |
+info: [SelBlocks] branch => @7: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |continue | xname=="dogbert" |  |
+info: [SelBlocks] branch => @7: [forXml|${forXmlFileName}]
+info: Executing: |forXml | ${forXmlFileName} |  |
+info: Executing: |continue | xname=="dogbert" |  |
+info: Executing: |break | xname=="wally" |  |
+info: [SelBlocks] branch => @11: [endForXml]
+info: Executing: |endForXml |  |  |
+info: Executing: |assertEmitted | "iter=dilbert" |  |
+info: Starting test /selenium-server/tests/nested-loops.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | i, n, uname |  |
+info: Executing: |startTimer |  |  |
+info: Executing: |store | 2 | i |
+info: Executing: |emit | "START ${i}" |  |
+info: Executing: |while | i > 0 |  |
+info: Executing: |emit | "while=${i}" |  |
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: [SelBlocks] branch => @17: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |storeEval | ${i}-1 | i |
+info: script is: 2-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: Executing: |emit | "while=${i}" |  |
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: Executing: |emit | "foreach=${uname}" |  |
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: Executing: |emit | "FOR=${n}" |  |
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: Executing: |emit | "for=${n}" |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @12: [for|n = 7; n <= 8; n++]
+info: Executing: |for | n = 7; n <= 8; n++ |  |
+info: [SelBlocks] branch => @14: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @10: [for|n = 2; n <=3; n++]
+info: Executing: |for | n = 2; n <=3; n++ |  |
+info: [SelBlocks] branch => @15: [endFor]
+info: Executing: |endFor |  |  |
+info: Executing: |emit | "endFor ${n}" |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @8: [foreach|uname|"dilbert", "dogbert"]
+info: Executing: |foreach | uname | "dilbert", "dogbert" |
+info: [SelBlocks] branch => @17: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |storeEval | ${i}-1 | i |
+info: script is: 1-1
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @19: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |emit | "END ${i}" |  |
+info: Executing: |timerElapsed |  |  |
+info: [SelBench] 3.304 sec elapsed: 
+info: Executing: |assertEmitted | "START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2" |  |
+info: Starting test /selenium-server/tests/function.html
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |assertEval | "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}" | true |
+info: script is: "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}"
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @3: [call|doSomething|sname = "dilbert,Q", srole = "goof"]
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: Executing: |assertEval | "${_result}" === "sname=dilbert,Q,srole=goof" | true |
+info: script is: "sname=dilbert,Q,srole=goof" === "sname=dilbert,Q,srole=goof"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |function | doSomething | sname |
+info: [SelBlocks] branch => @8: [endFunction|doSomething]
+info: Executing: |endFunction | doSomething |  |
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @10: [call|doSomething|sname = "dogbert", srole = "woof"]
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: Executing: |assertEval | "${_result}" === "sname=dogbert,srole=woof" | true |
+info: script is: "sname=dogbert,srole=woof" === "sname=dogbert,srole=woof"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @13: [call|doSomething|sname = "ratbert", srole = "squeak"]
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: Executing: |assertEval | "${_result}" === "sname=ratbert,srole=squeak" | true |
+info: script is: "sname=ratbert,srole=squeak" === "sname=ratbert,srole=squeak"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @17: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |assertEval | "${_result}" === "sname=${sname},srole=super=user" | true |
+info: script is: "sname=asok,srole=super=user" === "sname=asok,srole=super=user"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @6: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @17: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |assertEval | "${_result}" === "sname=${sname},srole=super=user" | true |
+info: script is: "sname=alice,srole=super=user" === "sname=alice,srole=super=user"
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: [SelBlocks] branch => @20: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |assertEval | "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}" | true |
+info: script is: "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}"
+info: Executing: |expectError | "Function does not exist: NONEXISTENT" |  |
+info: Executing: |call | NONEXISTENT |  |
+error: [SelBlocks] Error @23: [call|NONEXISTENT] Function does not exist: NONEXISTENT
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |script | doDeprecated | sname |
+warn: [SelBlocks] The script command has been deprecated and will be removed in future releases. Please use function instead.
+info: [SelBlocks] branch => @27: [endScript|doDeprecated]
+info: Executing: |endScript | doDeprecated |  |
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: [SelBlocks] branch => @25: [script|doDeprecated|sname]
+info: Executing: |script | doDeprecated | sname |
+warn: [SelBlocks] The script command has been deprecated and will be removed in future releases. Please use function instead.
+info: Executing: |return | "sname=${sname},srole=${srole}" |  |
+info: [SelBlocks] branch => @28: [call|doDeprecated|sname = "wally", srole = "lazy"]
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: Executing: |assertEval | "${_result}" === "sname=wally,srole=lazy" | true |
+info: script is: "sname=wally,srole=lazy" === "sname=wally,srole=lazy"
+info: Executing: |deleteVars | sname, srole |  |
+info: Starting test /selenium-server/tests/function-recursive.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | degree, n, _result, ud |  |
+info: Executing: |store | 7 | degree |
+info: Executing: |startTimer |  | factorial ${degree} |
+info: Executing: |call | fac | n=degree |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: [SelBlocks] branch => @11: [else]
+info: Executing: |else |  |  |
+info: Executing: |call | fac | n = n-1 |
+info: [SelBlocks] branch => @8: [function|fac|n]
+info: Executing: |function | fac | n |
+info: Executing: |if | n <= 1 |  |
+info: Executing: |return | 1 |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @12: [call|fac|n = n-1]
+info: Executing: |call | fac | n = n-1 |
+info: Executing: |emit | _result |  |
+info: Executing: |return | n * _result |  |
+info: [SelBlocks] branch => @5: [call|fac|n=degree]
+info: Executing: |call | fac | n=degree |
+info: Executing: |timerElapsed |  |  |
+info: [SelBench] 1.226 sec elapsed: factorial 7
+info: Executing: |emit | degree + "!=" + _result |  |
+info: Executing: |function | fac | n |
+info: [SelBlocks] branch => @16: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |function | uno |  |
+info: [SelBlocks] branch => @23: [endFunction|uno]
+info: Executing: |endFunction | uno |  |
+info: Executing: |function | due |  |
+info: [SelBlocks] branch => @30: [endFunction|due]
+info: Executing: |endFunction | due |  |
+info: Executing: |store | 5 | ud |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 5-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | due |  |
+info: [SelBlocks] branch => @24: [function|due]
+info: Executing: |function | due |  |
+info: Executing: |emit | "DUE" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 4-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 3-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | due |  |
+info: [SelBlocks] branch => @24: [function|due]
+info: Executing: |function | due |  |
+info: Executing: |emit | "DUE" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 2-1
+info: Executing: |if | ud > 0 |  |
+info: Executing: |call | uno |  |
+info: [SelBlocks] branch => @17: [function|uno]
+info: Executing: |function | uno |  |
+info: Executing: |emit | "UNO" |  |
+info: Executing: |storeEval | ${ud}-1 | ud |
+info: script is: 1-1
+info: Executing: |if | ud > 0 |  |
+info: [SelBlocks] branch => @22: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @28: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | due |  |
+info: [SelBlocks] branch => @21: [call|due]
+info: Executing: |call | due |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @28: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | due |  |
+info: [SelBlocks] branch => @21: [call|due]
+info: Executing: |call | due |  |
+info: Executing: |endIf |  |  |
+info: Executing: |endFunction | uno |  |
+info: [SelBlocks] branch => @32: [call|uno]
+info: Executing: |call | uno |  |
+info: Executing: |assertEmitted | "1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO" |  |
+info: Starting test /selenium-server/tests/issue-2-function.html
+info: Executing: |function | xyz |  |
+info: [SelBlocks] branch => @3: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | xyz |  |
+info: [SelBlocks] branch => @1: [function|xyz]
+info: Executing: |function | xyz |  |
+info: Executing: |log | 'here' |  |
+info: [SelBench] here
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @4: [call|xyz]
+info: Executing: |call | xyz |  |
+info: Starting test /selenium-server/tests/exitTest%20-%20base%20case.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/exitTest%20-%20from%20within%20a%20loop.html
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: [SelBlocks] branch => @4: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |if | i === 3 |  |
+info: [SelBlocks] branch => @7: [endIf]
+info: Executing: |endIf |  |  |
+info: Executing: |endFor |  |  |
+info: [SelBlocks] branch => @1: [for|i=0; i < 5; i++]
+info: Executing: |for | i=0; i < 5; i++ |  |
+info: Executing: |if | i == 3 |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/exitTest%20-%20from%20within%20a%20function.html
+info: Executing: |call | doSubExit |  |
+info: [SelBlocks] branch => @3: [function|doSubExit]
+info: Executing: |function | doSubExit |  |
+info: Executing: |exitTest |  |  |
+info: [SelBlocks] TEST HALTED
+info: Starting test /selenium-server/tests/GlobalFunctions.html
+info: Executing: |getEval | globalStoredVars = {}; |  |
+info: script is: globalStoredVars = {};
+info: Executing: |function | setGlobalVar |  |
+info: [SelBlocks] branch => @4: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Starting test /selenium-server/tests/CallGlobalFunction.html
+info: Executing: |getEval | globalStoredVars.aGlobalVar = "reset"; |  |
+info: script is: globalStoredVars.aGlobalVar = "reset";
+info: Executing: |assertNotEval | globalStoredVars.aGlobalVar; | set |
+info: script is: globalStoredVars.aGlobalVar;
+info: Executing: |assertEval | globalStoredVars.aGlobalVar; | reset |
+info: script is: globalStoredVars.aGlobalVar;
+info: Executing: |call | GlobalFunctions.setGlobalVar |  |
+info: [SelBlocks] branch => @2: [assertNotEval|globalStoredVars.aGlobalVar;|set]
+info: Executing: |function | setGlobalVar |  |
+info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; |  |
+info: script is: globalStoredVars.aGlobalVar = "set";
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @4: [call|GlobalFunctions.setGlobalVar]
+info: Executing: |call | GlobalFunctions.setGlobalVar |  |
+info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set |
+info: script is: globalStoredVars.aGlobalVar;
+info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20Base.html
+info: Executing: |store | original | x |
+info: Executing: |store | original | y |
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |function | bob | x,y |
+info: [SelBlocks] branch => @8: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | bob | x="overwritten" |
+info: [SelBlocks] branch => @5: [function|bob|x,y]
+info: Executing: |function | bob | x,y |
+info: Executing: |assertEval | "${x}" === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |assertEval | storedVars.y === undefined | true |
+info: script is: storedVars.y === undefined
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @9: [call|bob|x="overwritten"]
+info: Executing: |call | bob | x="overwritten" |
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | storedVars.y === undefined | false |
+info: script is: storedVars.y === undefined
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20With%20Default%20Values.html
+info: Executing: |store | original | x |
+info: Executing: |store | original | y |
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: [SelBlocks] branch => @8: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |function | defaultsTest | x="fn default x",y="fn default y" |
+info: [SelBlocks] branch => @16: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | defaultsTest |  |
+info: [SelBlocks] branch => @9: [function|defaultsTest|x="fn default x",y="fn default y"]
+info: Executing: |function | defaultsTest | x="fn default x",y="fn default y" |
+info: Executing: |assertEval | ${x} === "fn default x" | true |
+info: script is: "fn default x" === "fn default x"
+info: Executing: |store | "overwritten" | x |
+info: Executing: |assertEval | ${x} === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |assertEval | ${y} === "fn default y" | true |
+info: script is: "fn default y" === "fn default y"
+info: Executing: |store | "overwritten" | y |
+info: Executing: |assertEval | ${y} === "overwritten" | true |
+info: script is: "overwritten" === "overwritten"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @17: [call|defaultsTest]
+info: Executing: |call | defaultsTest |  |
+info: Executing: |call | leakTest |  |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @18: [call|leakTest]
+info: Executing: |call | leakTest |  |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | y = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @25: [call|leakTest|y = "overwritten"]
+info: Executing: |call | leakTest | y = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | x = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @32: [call|leakTest|x = "overwritten"]
+info: Executing: |call | leakTest | x = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |call | leakTest | x = "overwritten", y = "overwritten" |
+info: [SelBlocks] branch => @5: [function|leakTest|x="fn default x",y="fn default y"]
+info: Executing: |function | leakTest | x="fn default x",y="fn default y" |
+info: Executing: |store | overwritten | x |
+info: Executing: |store | overwritten | y |
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @39: [call|leakTest|x = "overwritten", y = "overwritten"]
+info: Executing: |call | leakTest | x = "overwritten", y = "overwritten" |
+info: Executing: |assertEval | "${x}" === "fn default x" | false |
+info: script is: "original" === "fn default x"
+info: Executing: |assertEval | "${x}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${x}" === "original"; | true |
+info: script is: "original" === "original";
+info: Executing: |assertEval | "${y}" === "fn default y" | false |
+info: script is: "original" === "fn default y"
+info: Executing: |assertEval | "${y}" === "overwritten" | false |
+info: script is: "original" === "overwritten"
+info: Executing: |assertEval | "${y}" === "original"; | true |
+info: script is: "original" === "original";
+info: Starting test /selenium-server/tests/StoreLocal%20-%20Function%20Scope.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |storeLocal | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @12: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/StoreGlobal%20-%20Function%20Scope.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.g = null; |  |
+info: script is: storedVarsGlobal.g = null;
+info: Executing: |assertEval | storedVarsGlobal.g === null; | true |
+info: script is: storedVarsGlobal.g === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |storeGlobal | this is stored globally | g |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @10: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Starting test /selenium-server/tests/StoreGlobal%20-%20While%20Scope.html
+info: Executing: |getEval | storedVarsGlobal.g = null; |  |
+info: script is: storedVarsGlobal.g = null;
+info: Executing: |assertEval | storedVarsGlobal.g === null; | true |
+info: script is: storedVarsGlobal.g === null;
+info: Executing: |store | 1 | i |
+info: Executing: |while | i > 0 |  |
+info: Executing: |store | 0 | i |
+info: Executing: |storeGlobal | this is stored globally | g |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @4: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @11: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEval | storedVarsGlobal.g === "this is stored globally" | true |
+info: script is: storedVarsGlobal.g === "this is stored globally"
+info: Executing: |assertEval | storedVars.g === "this is stored globally" | true |
+info: script is: storedVars.g === "this is stored globally"
+info: Executing: |assertEval | storedVarsLocal.g === "this is stored globally" | true |
+info: script is: storedVarsLocal.g === "this is stored globally"
+info: Executing: |assertEval | "${g}" === "this is stored globally" | true |
+info: script is: "this is stored globally" === "this is stored globally"
+info: Starting test /selenium-server/tests/StoreLocal%20-%20While%20Scope.html
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |store | 1 | i |
+info: Executing: |while | i > 0 |  |
+info: Executing: |store | 0 | i |
+info: Executing: |storeLocal | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @6: [while|i > 0]
+info: Executing: |while | i > 0 |  |
+info: [SelBlocks] branch => @13: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/Store%20-%20Behaves%20as%20StoreLocal.html
+info: Executing: |function | blockScopeVars |  |
+info: [SelBlocks] branch => @7: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |getEval | storedVars.l = null; |  |
+info: script is: storedVars.l = null;
+info: Executing: |assertEval | storedVars.l === null; | true |
+info: script is: storedVars.l === null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |call | blockScopeVars |  |
+info: [SelBlocks] branch => @1: [function|blockScopeVars]
+info: Executing: |function | blockScopeVars |  |
+info: Executing: |store | this is stored locally | l |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | true |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | true |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | true |
+info: script is: "this is stored locally" === "this is stored locally"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @12: [call|blockScopeVars]
+info: Executing: |call | blockScopeVars |  |
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored locally" | false |
+info: script is: storedVarsGlobal.l === "this is stored locally"
+info: Executing: |assertEval | storedVars.l === "this is stored locally" | false |
+info: script is: storedVars.l === "this is stored locally"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored locally" | false |
+info: script is: storedVarsLocal.l === "this is stored locally"
+info: Executing: |assertEval | "${l}" === "this is stored locally" | false |
+info: script is: "${l}" === "this is stored locally"
+info: Starting test /selenium-server/tests/Function%20-%20Can%20Return%20Value.html
+info: Executing: |function | returnsValue |  |
+info: [SelBlocks] branch => @3: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |call | returnsValue |  |
+info: [SelBlocks] branch => @1: [function|returnsValue]
+info: Executing: |function | returnsValue |  |
+info: Executing: |return | "banana" |  |
+info: [SelBlocks] branch => @4: [call|returnsValue]
+info: Executing: |call | returnsValue |  |
+info: Executing: |assertEval | "${_result}" === "banana" | true |
+info: script is: "banana" === "banana"
+info: Starting test /selenium-server/tests/StoreAt%20-%20Function%20Scope%20Nesting.html
+info: Executing: |function | storel |  |
+info: [SelBlocks] branch => @9: [endFunction]
+info: Executing: |endFunction |  |  |
+info: Executing: |getEval | storedVarsGlobal.notDefined = null |  |
+info: script is: storedVarsGlobal.notDefined = null
+info: Executing: |assertEval | storedVarsGlobal.notDefined === null | true |
+info: script is: storedVarsGlobal.notDefined === null
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |storeLocal | exists in parent | l |
+info: Executing: |assertEval | storedVars.l === "exists in parent"; | true |
+info: script is: storedVars.l === "exists in parent";
+info: Executing: |call | storel |  |
+info: [SelBlocks] branch => @1: [function|storel]
+info: Executing: |function | storel |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |endFunction |  |  |
+info: [SelBlocks] branch => @16: [call|storel]
+info: Executing: |call | storel |  |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Starting test /selenium-server/tests/StoreAt%20-%20While%20Scope%20Nesting.html
+info: Executing: |getEval | storedVarsGlobal.notDefined = null |  |
+info: script is: storedVarsGlobal.notDefined = null
+info: Executing: |assertEval | storedVarsGlobal.notDefined === null | true |
+info: script is: storedVarsGlobal.notDefined === null
+info: Executing: |getEval | storedVarsGlobal.l = null; |  |
+info: script is: storedVarsGlobal.l = null;
+info: Executing: |assertEval | storedVarsGlobal.l === null; | true |
+info: script is: storedVarsGlobal.l === null;
+info: Executing: |storeLocal | exists in parent | l |
+info: Executing: |assertEval | storedVars.l === "exists in parent"; | true |
+info: script is: storedVars.l === "exists in parent";
+info: Executing: |storeLocal | 3 | x |
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: Executing: |storeAt | this ends up global | notDefined |
+warn: [SelBlocks] notDefined not found, setting global variable
+info: Executing: |storeAt | this is stored in an ancestor | l |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Executing: |storeEvalLocal | x -= 1 |  |
+info: Executing: |endWhile |  |  |
+info: [SelBlocks] branch => @8: [while|x !== 0]
+info: Executing: |while | x !== 0 |  |
+info: [SelBlocks] branch => @17: [endWhile]
+info: Executing: |endWhile |  |  |
+info: Executing: |deleteVar | x |  |
+info: Executing: |assertEval | storedVarsGlobal.notDefined === "this ends up global" | true |
+info: script is: storedVarsGlobal.notDefined === "this ends up global"
+info: Executing: |assertEval | storedVarsGlobal.l === "this is stored in an ancestor" | false |
+info: script is: storedVarsGlobal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVars.l === "this is stored in an ancestor" | true |
+info: script is: storedVars.l === "this is stored in an ancestor"
+info: Executing: |assertEval | storedVarsLocal.l === "this is stored in an ancestor" | true |
+info: script is: storedVarsLocal.l === "this is stored in an ancestor"
+info: Executing: |assertEval | "${l}" === "this is stored in an ancestor" | true |
+info: script is: "this is stored in an ancestor" === "this is stored in an ancestor"
+info: Starting test /selenium-server/tests/sendkeys%20keys%20are%20preserved.html
+info: Executing: |assertEval | "KEY_ENTER" in storedVars | true |
+info: script is: "KEY_ENTER" in storedVars
+info: Executing: |assertEval | "KEY_TAB" in storedVars | true |
+info: script is: "KEY_TAB" in storedVars
+info: Executing: |assertEval | "KEY_BACKSPACE" in storedVars | true |
+info: script is: "KEY_BACKSPACE" in storedVars
+
\ No newline at end of file diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd new file mode 100644 index 0000000..c9c5951 --- /dev/null +++ b/testUserExtension/runTestsOnServer.cmd @@ -0,0 +1,470 @@ +@ echo off + +SETLOCAL + +REM if the autotests don't complete within the given time, the server will shut +REM down and close the browser windows. +SET /a autotestTimeoutInSeconds=180 +REM the root of the project +REM C:\projects\selenium\selblocks\SelBlocks\ +SET projectRoot=%~dp0..\ +REM parts of the baseURL used when the server is started +SET protocol=http +SET host=htmlpreview.github.io +SET port=80 +REM the port that selenium server will run on +SET seleniumServerPort=4444 +REM the name of the test suite to load into the server +SET testSuiteFileName=_SelBlocks-TestSuite.html +REM the name of the directory that holds scripts for generating parts of the project +SET buildScriptsDirName=build +REM the script for building the release version of the user-extensions.js file +SET userExtensionsBuildScriptFileName=createSelblocksUserExtensions.cmd +REM directory that holds the selenese tests +SET testsDirName=sel-blocksTests +REM the path to selbench's user extension, for generating testing versions of +REM this user extension (not used in selbench project, obviously) +SET selbenchUserExtension=%projectRoot%..\..\selbench\SelBench\user extension\user-extensions.js +REM directory that holds parts of the user extension and the generated +REM "release" version of the extension. +SET userExtensionDirName=user extension +REM holds scripts, logs, results, and other files for testing the user extension +REM the testing version of the extension is generated here. +SET testUserExtensionDirName=testUserExtension +REM console output from the server is redirected into this file when +REM the log option is used. +SET serverLogFileName=Selenium Server Log.txt +SET serverLog=%projectRoot%\%testUserExtensionDirName%\%serverLogFileName% +REM Autotesting results will be placed in this file. The browser chosen will be +REM added to the end of the file name. (results-firefox.html) +SET resultsLogFileName=results +SET resultsLog=%projectRoot%\%testUserExtensionDirName%\%resultsLogFileName% +REM the location of selenium-server-standalone*.jar, chromedriver.exe, and +REM IEDriverServer.exe +REM C:\projects\selenium\server\ +SET seleniumServerLocation=%projectRoot%\..\..\server\ +REM the filesystem path to the test suite file. +SET testSuiteFile=%projectRoot%\%testsDirName%\%testSuiteFileName% +REM this is the base url setting for selenium server +SET baseURL=%protocol%://%host%:%port% +REM the server debug path to the test suite. This is not the same as the +REM autotesting url. +SET testSuiteURL=./../%testSuiteFileName% +REM the release version of the user extension. +SET defaultUserExtensions=%projectRoot%\%userExtensionDirName%\user-extensions.js +REM the testing version of the user extension. +SET testUserExtensions=%projectRoot%\%testUserExtensionDirName%\user-extensions.js +REM Selenium server roots at whatever directory contains the user-extensions +REM file. This is just a copy of the testing version of the user extension. +SET serverDebugUserExtensions=%projectRoot%\%testsDirName%\user-extensions.js +REM Sets %seleniumServerJar% by selecting the last found +REM selenium-server-standalone file in +REM %seleniumServerLocation% I think it always finds the one with the highest +REM version number but I'm not sure. +FOR %%I IN (%seleniumServerLocation%\selenium-server-standalone*.jar) DO SET seleniumServerJar=%%~dpnxI + +CALL :parameterHandler %* +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:parameterHandler + SETLOCAL ENABLEDELAYEDEXPANSION + IF ["%~1"]==["-h"] ( + CALL :showHelp + ENDLOCAL + EXIT /B 0 + ) ELSE IF ["%~1"]==["-help"] ( + CALL :showHelp + ENDLOCAL + EXIT /B 0 + ) ELSE IF ["%~1"]==[""] ( + CALL :startAutotest + IF NOT !ERRORLEVEL! EQU 0 ( + CALL :startDebugTestSuite + ) + ) ELSE IF [%~1]==[start-autotest] ( + IF NOT ["%~2"]==[""] ( + IF ["%~2"]==["all"] ( + CALL :startAutotest "firefox" "nolog" + CALL :startAutotest "piiexplore" "nolog" + CALL :startAutotest "googlechrome" "nolog" + ) ELSE ( + CALL :startAutotest "%~2" "%~3" + ) + ) ELSE ( + CALL :startAutotest + ) + ) ELSE IF [%~1]==[start-debug] ( + IF NOT ["%~2"]==[""] ( + CALL :startDebugTestSuite "%~2" + ) ELSE ( + CALL :startDebugTestSuite + ) + ) ELSE IF [%~1]==[open-selenium-server] ( + CALL :seleniumOpenSeleniumServer "%~2" + ) ELSE IF [%~1]==[open-driver] ( + CALL :seleniumOpenSeleniumServerDriver "%~2" + ) ELSE IF [%~1]==[open-core] ( + CALL :seleniumOpenSeleniumServerCore "%~2" + ) ELSE ( + ECHO ERROR: I don't know what you want to do. + ECHO ERROR: %* + ) +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:showHelp +SETLOCAL + ECHO. + ECHO GLORIOUS TEST RUNNER RUNS TESTS GLORIOUSLY + ECHO. + ECHO start without arguments to run autotests in firefox and automatically + ECHO show logs / start debug on failure. + ECHO. + ECHO start-autotest [browser] [nolog] + ECHO Where browser is a valid browser for Selenium, minus the initial asterisk + ECHO Where supplying the second argument as "nolog" will stop the server log + ECHO from opening automatically on failure. If you specify the browser as + ECHO "all" then the second argument is ignored. It will not open the logs + ECHO automatically, since they're deleted after each run with the browsers. + ECHO You basically just watch "firefox", "piiexplore", and "googlechrome" + ECHO go through the default test suite. It doesn't take long. If they don't + ECHO crash or timeout on the tests then there will be results-[browser].html + ECHO created. So really you don't have to watch, but it's fun to watch. + ECHO. + ECHO start-debug [test suite name] + ECHO Where test suite name is a test suite located in your test suites + ECHO directory. + ECHO. + ECHO open-selenium-server [subdirectory or page] + ECHO Where subdirectory or page is some subdirectory of wherever the selenium + ECHO server is rooted. Currently this is the project root. + ECHO. + ECHO open-driver [querystring] + ECHO Where querystring is the initial query to send to the RC server. By + ECHO default it gets a new firefox session. Your default browser should open + ECHO to a page where you can send commands through the address bar. The + ECHO browser under control will have a status window and the window under + ECHO remote control. + ECHO. + ECHO open-core [subdirectory or page] + ECHO Opens the /selenium-server/core/[subdirectory or page] The pages + ECHO available here are the ones packed into the selenium-core directory of + ECHO the selenium-server-standalone-[version].jar file + ECHO. +ENDLOCAL +EXIT /B 0 + +:cleanupLogsAndResults + SETLOCAL + REM deletes the existing server logs + FOR %%I IN ("%serverLog%*") DO DEL /Q "%%I" + + REM deletes the existing auto testing results + FOR %%I IN (results-*.html) DO DEL /Q "%%I" +ENDLOCAL +EXIT /B 0 + +:generateTestingUserExtension + SETLOCAL + REM creates the user extension with selbench + + DEL /Q %testUserExtensions% + + START "Regenerating default user-extensions.js" /WAIT /MIN CMD /C "%projectRoot%\%buildScriptsDirName%\%userExtensionsBuildScriptFileName%" + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Could not generate user-extensions.js + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + + IF DEFINED selbenchUserExtension ( + COPY "%selbenchUserExtension%"+"%defaultUserExtensions%" /B "%testUserExtensions%" /B + ) ELSE ( + COPY "%defaultUserExtensions%" /B "%testUserExtensions%" /B + ) +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:waitForFile + SETLOCAL + SET /a count=0 + SET /a max=11 + SET filename= + + IF ["%~1"]==[""] ( + ECHO ERROR: No file given to wait for. + ENDLOCAL + EXIT /B 1 + ) ELSE ( + SET filename=%~1 + ) + IF ["%~2"]==[""] ( + ECHO WARNING: No maximum count given, defaulting to %max%. + ) ELSE ( + SET /a max=%2 + ) + ECHO INFO: Watching for file: "%filename%" for approximately %max% seconds. +:waitForFileLoop + IF EXIST "%filename%" ( + ENDLOCAL + EXIT /B 0 + ) ELSE IF %count% LSS %max% ( + ECHO INFO: File check %count% + SET /a count+=1 + PING -n 2 127.0.0.1>nul + GOTO :waitForFileLoop + ) ELSE ( + ECHO ERROR: The file never showed up. + ENDLOCAL + EXIT /B 1 + ) +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:openFile + SETLOCAL ENABLEDELAYEDEXPANSION + REM opens the file in the default application. + IF ["%~1"]==[""] ( + ECHO ERROR: No file specified. + ENDLOCAL + EXIT /B 1 + ) + SET "str=%~1" + REM Collapses multiple backslashes into a single backslash, unless there are + REM more than 10 in a row... + FOR /l %%i in (1,1,10) DO SET str=!str:\\=\! + CALL :waitForFile "!str!" %~2 + IF NOT %ERRORLEVEL% EQU 0 ( + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + ECHO INFO: Opening "!str!" + explorer "!str!" +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:startAutotestServer + SETLOCAL + IF ["%~1"]==[""] ( + ECHO ERROR: No browser specified. + ENDLOCAL + EXIT /B 1 + ) ELSE ( + ECHO INFO: Attempting to start "%~1" browser for automated testing. + ) + SET browser=%~1 + REM firefox, piiexplore, googlechrome + + DEL /Q %serverDebugUserExtensions% + + REM copies the testing user extensions file to the debug location. + COPY "%testUserExtensions%" /B "%serverDebugUserExtensions%" /B + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Could not copy user-extensions.js to the project root. + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + + REM browsers currently available + + REM *firefox + REM *mock + REM *firefoxproxy + REM *pifirefox + REM *chrome + REM *iexploreproxy + REM *iexplore + REM *firefox3 + REM *safariproxy + REM *googlechrome + REM *konqueror + REM *firefox2 + REM *piiexplore + REM *safari + REM *firefoxchrome + REM *opera + REM *webdriver + REM *iehta + REM *custom + + REM runs test suite specified by testSuiteFile, in the given browser + start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" ^ + -port %seleniumServerPort% ^ + -Dwebdriver.ie.driver="%seleniumServerLocation%\IEDriverServer.exe" ^ + -Dwebdriver.chrome.driver="%seleniumServerLocation%\chromedriver.exe" ^ + -userExtensions "%serverDebugUserExtensions%" ^ + -log "%serverLog%" -browserSideLog ^ + -htmlSuite "*%browser%" "%baseURL%" "%testSuiteFile%" "%resultsLog%-%browser%.html" ^ + -timeout %autotestTimeoutInSeconds% + +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:openServerLog + SETLOCAL ENABLEDELAYEDEXPANSION + SET str=%serverLog% + REM Collapses multiple backslashes into a single backslash, unless there are + REM more than 10 in a row... + FOR /l %%i in (1,1,10) DO SET str=!str:\\=\! + CALL :openFile "!str!" + ENDLOCAL +EXIT /B %ERRORLEVEL% + +:startAutotest + SETLOCAL + IF ["%~1"]==[""] ( + ECHO WARN: No browser specified. Defaults to firefox + SET browser=firefox + ) ELSE ( + SET browser=%~1 + ) + REM firefox, piiexplore, googlechrome + + IF ["%~2"]==["nolog"] ( + ECHO WARN: Will not open Server Log on failure. + SET nolog=true + ) ELSE ( + SET nolog=false + ) + +REM CALL :cleanupLogsAndResults +REM IF NOT %ERRORLEVEL% EQU 0 ( +REM ENDLOCAL +REM EXIT /B %ERRORLEVEL% +REM ) + + CALL :generateTestingUserExtension + IF NOT %ERRORLEVEL% EQU 0 ( + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + + CALL :startAutotestServer "%browser%" + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Something went wrong with the server or the tests timed out. Check the logs. + IF %nolog%==true ( + ECHO INFO: Logs can be found at: %serverLog% + ) ELSE ( + CALL :openServerLog + ) + ) + + IF %nolog%==true ( + ECHO INFO: Test results can be found at: "%resultsLog%-%browser%.html" + ) ELSE ( + REM opens the results in the default browser + CALL :openFile "%resultsLog%-%browser%.html" + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Could not open browser to the test results. + ENDLOCAL + EXIT /B 1 + ) + ) +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:startDebugServer + SETLOCAL + DEL /Q %serverDebugUserExtensions% + + REM copies the testing user extensions file to the debug location. + COPY "%testUserExtensions%" /B "%serverDebugUserExtensions%" /B + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Could not copy user-extensions.js to the project root. + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + + REM Starts the server and roots it at the directory where + REM %serverDebugUserExtensions% is located + REM no html results file will be generated but you can listen to the + REM HTTP POST requests made + START "selenium server" /MAX java -jar "%seleniumServerJar%" ^ + -port %seleniumServerPort% ^ + -Dwebdriver.ie.driver="%seleniumServerLocation%\IEDriverServer.exe" ^ + -Dwebdriver.chrome.driver="%seleniumServerLocation%\chromedriver.exe" ^ + -userExtensions "%serverDebugUserExtensions%" ^ + -debug + + REM we don't wait for the server because debugging might take a long time. + REM this also means we don't listen for the server to exit with some errorlevel. +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:startDebugTestSuite + SETLOCAL + REM alternate test suites may be specified + IF NOT ["%~1"]==[""] ( + SET "testSuiteURL=./../%testsDirName%/%~1" + ) + + CALL :startDebugServer + + REM opens the default web browser to the server test runner and sets the test + REM path to the test suite. + CALL :seleniumOpenTestSuite "%testSuiteURL%" + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Could not open browser to the test suite. + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:seleniumOpenTestSuite +SETLOCAL + IF ["%~1"]==[""] ( + ECHO ERROR: No test specified. + ENDLOCAL + EXIT /B 1 + ) + + SET sc=%%3A + SET fs=%%2F + SET "str=%baseURL%/selenium-server/core/TestRunner.html?test=%~1" + SET "str=%str%&resultsUrl=./selenium-server/postResults" + SET "str=%str%&baseUrl=%protocol%%sc%%fs%%fs%%host%%sc%%port%" + SET "str=%str%&multiWindow=on" + SET "str=%str%&defaultLogLevel=info" + + IF NOT ["%~2"]==[""] ( + SET "str=%str%&auto=true" + ) + + explorer "%str%" +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 + +:seleniumOpenSeleniumServer +SETLOCAL + CALL :startDebugServer + explorer "%baseURL%/selenium-server/%~1" +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 + +:seleniumOpenSeleniumServerDriver +SETLOCAL + REM java -jar selenium-server.jar -interactive + REM cmd=getNewBrowserSession&1=*firefox&2=http://www.google.com + REM Got result: OK,260113 on session 260113 + REM cmd=open&1=http://www.google.com&2=hello world&sessionId= + CALL :startDebugServer + IF ["%~1"]==[""] ( + explorer "%baseURL%/selenium-server/driver?cmd=getNewBrowserSession&1=*firefox&2=http://www.google.com" + ) ELSE ( + explorer "%baseURL%/selenium-server/driver?%~1" + ) +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 + +:seleniumOpenSeleniumServerCore +SETLOCAL + CALL :startDebugServer + explorer "%baseURL%/selenium-server/core/%~1" +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 diff --git a/user extension/SeleniumHTMLRunner.cmd b/user extension/SeleniumHTMLRunner.cmd new file mode 100644 index 0000000..f9688b2 --- /dev/null +++ b/user extension/SeleniumHTMLRunner.cmd @@ -0,0 +1,28 @@ +@echo off + +SET browser=firefox + +REM change this to the base url for your tests. +SET baseURL=http://www.google.com + +SET seleniumServerPort=4444 + +REM if the tests don't complete in this many seconds the server will kill the +REM browsers. +SET autotestTimeoutInSeconds=300 + +REM change these to paths on your own system. Keep the user-extensions.js file +REM in the root of your test suites directory. + +SET fullPathToTestSuiteFile=C:\selenium tests\cases and suites\TestSuite.html +SET fullPathToUserExtensions=C:\selenium tests\cases and suites\user-extensions.js +SET fullPathToTestResultsFileLocation=C:\selenium tests\results and logs\ +SET fullPathToSeleniumServerJar=C:\selenium server\selenium-server-standalone-2.43.1.jar + + +REM runs test suite specified by testSuiteFile, in the given browser +START "selenium server" /MAX java -jar "%fullPathToSeleniumServerJar%" ^ + -port %seleniumServerPort% ^ + -userExtensions "%fullPathToUserExtensions%" ^ + -htmlSuite "*%browser%" "%baseURL%" "%fullPathToTestSuiteFile%" "%fullPathToTestResultsFileLocation%Results-%browser%.html" ^ + -timeout %autotestTimeoutInSeconds% \ No newline at end of file diff --git a/user extension/scripts/config.js b/user extension/scripts/config.js new file mode 100644 index 0000000..5cd0854 --- /dev/null +++ b/user extension/scripts/config.js @@ -0,0 +1,103 @@ +/*jslint +indent:2, +maxerr:500, +plusplus:true + */ +/*globals +globalContext:true, +HtmlRunnerTestLoop:true, +Selenium:true, +htmlTestRunner:true + */ +globalContext = this; +globalContext.onServer = globalContext.onServer || true; +globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; + +(function () { +function seleniumResetInterceptor() { + var old_reset; + old_reset = Selenium.prototype.reset; + + Selenium.prototype.reset = function () { + function map_list(list, for_func, if_func) { + var i, + x, + mapped_list = []; + for (i = 0; i < list.length; ++i) { + x = list[i]; + // AJS: putaquiupariu + if (undefined === if_func || if_func(i, x)) { + mapped_list.push(for_func(i, x)); + } + } + return mapped_list; + } + + /*jslint unparam:true */ + function importCommands(i, x) { + var b = x.getCommand(); + if (x.hasOwnProperty('trElement')) { + b.type = "command"; + } else { + b.type = "comment"; + } + return b; + } + /*jslint unparam:false */ + + old_reset.call(this); + // if htmlTestRunner is defined... + if (!(htmlTestRunner === undefined || htmlTestRunner === null)) { + //TODO: map commands to real types instead of faking it + htmlTestRunner.currentTest.commands = map_list(htmlTestRunner.currentTest.htmlTestCase.getCommandRows(), importCommands); + // AJS: initializes private testCase (closure) to point to htmlTestRunner.currentTest (public testCase is not available under Core). + globalContext.testCase = htmlTestRunner.currentTest; + // the debugContext isn't there, but redirecting to the testCase seems to work. + globalContext.testCase.debugContext = globalContext.testCase; + var currentDebugIndex = globalContext.testCase.debugIndex; + Object.defineProperties(globalContext.testCase, { + "_secret_nextCommandRowIndex" : { + configurable : false, + enumerable : false, + writable : true, + value : undefined + }, + "debugIndex" : { + get : function () { return this._secret_nextCommandRowIndex; }, + set : function (x) { this._secret_nextCommandRowIndex = x; }, + configurable : false, + enumerable : true + }, + "nextCommandRowIndex" : { + get : function () { return this._secret_nextCommandRowIndex; }, + set : function (x) { this._secret_nextCommandRowIndex = x; }, + configurable : false, + enumerable : true + } + }); + globalContext.testCase.debugIndex = currentDebugIndex; + } + }; +} + +function patchServerEnvironment() { + + if (globalContext.scriptServerPatchApplied !== true) { + globalContext.testCase = {}; + HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; + HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { + this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); + this.commands = []; + }; + } + seleniumResetInterceptor(); + globalContext.serverPatchApplied = true; +} + +// There's an option to use user-extensions.js in the IDE +// but it runs the tests against the webdriver backed selenium +// which is a different API than the one that tests are written against... +if ((globalContext.onServer === true) && (globalContext.serverPatchApplied === false)) { + patchServerEnvironment(); +} +}()); \ No newline at end of file diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js new file mode 100644 index 0000000..dce49b7 --- /dev/null +++ b/user extension/user-extensions.js @@ -0,0 +1,2699 @@ +/*jslint +indent:2, +maxerr:500, +plusplus:true + */ +/*globals +globalContext:true, +HtmlRunnerTestLoop:true, +Selenium:true, +htmlTestRunner:true + */ +globalContext = this; +globalContext.onServer = globalContext.onServer || true; +globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; + +(function () { +function seleniumResetInterceptor() { + var old_reset; + old_reset = Selenium.prototype.reset; + + Selenium.prototype.reset = function () { + function map_list(list, for_func, if_func) { + var i, + x, + mapped_list = []; + for (i = 0; i < list.length; ++i) { + x = list[i]; + // AJS: putaquiupariu + if (undefined === if_func || if_func(i, x)) { + mapped_list.push(for_func(i, x)); + } + } + return mapped_list; + } + + /*jslint unparam:true */ + function importCommands(i, x) { + var b = x.getCommand(); + if (x.hasOwnProperty('trElement')) { + b.type = "command"; + } else { + b.type = "comment"; + } + return b; + } + /*jslint unparam:false */ + + old_reset.call(this); + // if htmlTestRunner is defined... + if (!(htmlTestRunner === undefined || htmlTestRunner === null)) { + //TODO: map commands to real types instead of faking it + htmlTestRunner.currentTest.commands = map_list(htmlTestRunner.currentTest.htmlTestCase.getCommandRows(), importCommands); + // AJS: initializes private testCase (closure) to point to htmlTestRunner.currentTest (public testCase is not available under Core). + globalContext.testCase = htmlTestRunner.currentTest; + // the debugContext isn't there, but redirecting to the testCase seems to work. + globalContext.testCase.debugContext = globalContext.testCase; + var currentDebugIndex = globalContext.testCase.debugIndex; + Object.defineProperties(globalContext.testCase, { + "_secret_nextCommandRowIndex" : { + configurable : false, + enumerable : false, + writable : true, + value : undefined + }, + "debugIndex" : { + get : function () { return this._secret_nextCommandRowIndex; }, + set : function (x) { this._secret_nextCommandRowIndex = x; }, + configurable : false, + enumerable : true + }, + "nextCommandRowIndex" : { + get : function () { return this._secret_nextCommandRowIndex; }, + set : function (x) { this._secret_nextCommandRowIndex = x; }, + configurable : false, + enumerable : true + } + }); + globalContext.testCase.debugIndex = currentDebugIndex; + } + }; +} + +function patchServerEnvironment() { + + if (globalContext.scriptServerPatchApplied !== true) { + globalContext.testCase = {}; + HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; + HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { + this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); + this.commands = []; + }; + } + seleniumResetInterceptor(); + globalContext.serverPatchApplied = true; +} + +// There's an option to use user-extensions.js in the IDE +// but it runs the tests against the webdriver backed selenium +// which is a different API than the one that tests are written against... +if ((globalContext.onServer === true) && (globalContext.serverPatchApplied === false)) { + patchServerEnvironment(); +} +}());// SelBlocks name-space +var selblocks = { name: "SelBlocks" }; + +// I don't want to redeclare the variable when the user-extension is generated +// I don't want the scripts to blow up when the firefox extension is used. +// This is an alias on the global scope that references the global scope. +globalContext = this; + +(function($$){ + + /* Starting with FF4 lots of objects are in an XPCNativeWrapper, + * and we need the underlying object for == and for..in operations. + */ + $$.unwrapObject = function(obj) { + if (typeof(obj) === "undefined" || obj == null) + return obj; + if (obj.wrappedJSObject) + return obj.wrappedJSObject; + return obj; + }; + + $$.fmtCmd = function(cmd) { + var c = cmd.command; + if (cmd.target) { c += "|" + cmd.target; } + if (cmd.value) { c += "|" + cmd.value; } + return c; + } + +}(selblocks)); +// selbocks name-space +(function($$){ + + /* LOG wrapper for SelBlocks-specific behavior + */ + function Logger() + { + this.error = function (msg) { this.logit("error", msg); }; + this.warn = function (msg) { this.logit("warn", msg); }; + this.info = function (msg) { this.logit("info", msg); }; + this.debug = function (msg) { this.logit("debug", msg); }; + this.trace = function (msg) { this.logit("debug", msg); }; // selenium doesn't have trace level + + this.logit = function (logLevel, msg) { + LOG[logLevel]("[" + $$.name + "] " + msg); // call the Selenium logger + }; + + // ==================== Stack Tracer ==================== + + this.genStackTrace = function(err) + { + var e = err || new Error(); + var stackTrace = []; + if (!e.stack) + stackTrace.push("No stack trace, (Firefox only)"); + else { + var funcCallPattern = /^\s*[A-Za-z0-9\-_\$]+\(/; + var lines = e.stack.split("\n"); + for (var i=0; i < lines.length; i++) { + if (lines[i].match(funcCallPattern)) + stackTrace.push(lines[i]); + } + if (!err) + stackTrace.shift(); // remove the call to genStackTrace() itself + } + return stackTrace; + }; + + this.logStackTrace = function(err) + { + var t = this.genStackTrace(err); + if (!err) + t.shift(); // remove the call to logStackTrace() itself + this.warn("__Stack Trace__"); + for (var i = 0; i < t.length; i++) { + this.warn("@@ " + t[i]); + } + }; + + // describe the calling function + this.descCaller = function() + { + var t = this.genStackTrace(new Error()); + if (t.length == 0) return "no client function"; + t.shift(); // remove the call to descCaller() itself + if (t.length == 0) return "no caller function"; + t.shift(); // remove the call to client function + if (t.length == 0) return "undefined caller function"; + return "caller: " + t[0]; + }; + } + + $$.LOG = new Logger(); + +}(selblocks)); +// selbocks name-space +(function($$){ + + /* Function interception + */ + $$.fn = {}; + + // execute the given function before each call of the specified function + $$.fn.interceptBefore = function(targetObj, targetFnName, _fn) { + var existing_fn = targetObj[targetFnName]; + targetObj[targetFnName] = function() { + _fn.call(this); + return existing_fn.call(this); + }; + }; + // execute the given function after each call of the specified function + $$.fn.interceptAfter = function(targetObj, targetFnName, _fn) { + var existing_fn = targetObj[targetFnName]; + targetObj[targetFnName] = function() { + existing_fn.call(this); + _fn.call(this); + }; + }; + // replace the specified function with the given function + $$.fn.interceptReplace = function(targetObj, targetFnName, _fn) { + targetObj[targetFnName] = function() { + //var existing_fn = targetObj[targetFnName] = _fn; + return _fn.call(this); + }; + }; + + $$.fn.interceptStack = []; + + // replace the specified function, saving the original function on a stack + $$.fn.interceptPush = function(targetObj, targetFnName, _fn, frameAttrs) { + // $$.LOG.warn("interceptPush " + (frameAttrs ? frameAttrs : "")); + var frame = { + targetObj: targetObj + ,targetFnName: targetFnName + ,savedFn: targetObj[targetFnName] + ,attrs: frameAttrs + }; + $$.fn.interceptStack.push(frame); + targetObj[targetFnName] = _fn; + }; + // restore the most recent function replacement + $$.fn.interceptPop = function() { + var frame = $$.fn.interceptStack.pop(); + // $$.LOG.warn("interceptPop " + (frame.attrs ? frame.attrs : "")); + frame.targetObj[frame.targetFnName] = frame.savedFn; + }; + + $$.fn.getInterceptTop = function() { + return $$.fn.interceptStack[$$.fn.interceptStack.length-1]; + }; + + // replace the specified function, but then restore the original function as soon as it is call + $$.fn.interceptOnce = function(targetObj, targetFnName, _fn) { + $$.fn.interceptPush(targetObj, targetFnName, function(){ + $$.fn.interceptPop(); // un-intercept + _fn.call(this); + }); + }; + +}(selblocks)); +/** Provides richer functionality than is available via Selenium xpathEvaluator. + * Used only by locator-builders, because it assumes a Firefox environment. + */ +// selbocks name-space +(function($$){ + + $$.xp = + { + /** + * Evaluate an xpathExpression against the given document object. + * @param {HTMLDOMDocument|Null} doc The document to evaluate the xpath expression + * against. Defaults to the document under test if it has the evaluate method, + * otherwise it uses the evaluate method from the selenium test runner window + * provided by the library loaded into selenium. + * @param {String} xpath The xpath expression to evaluate. + * @param {HTMLElement|Null} contextNode The effective root element for the + * xpath expression. Defaults to the document under test, falling back to + * the library loaded by selenium. + * @param {Number|Null} resultType The desired type of xpath result. + * constants may be used instead of numbers. Defaults to + * `XPathResult.ANY_TYPE`. + * @see https://developer.mozilla.org/en-US/docs/XPathResult + * @param {Function|Null} namespaceResolver The namespace resolver used to disambiguate + * namespaced elements in xhtml and xml docs. It will receive one argument: + * the (String) namespace prefix on the element and, it must return the + * string identifying the namespace that the element belongs to. In HTML + * this is usually null because nobody is using namespaces in HTML, no + * no matter how handy they are... + * @param {XPathResult|Null} resultObj Previous results from evaluating + * xpath expressions. + * @returns {XPathResult} Returns the XPathResult object containing the + * nodes found by the given query and specs. Will use the given `resultObj` + * if not null. + */ + evaluateXpath: function(doc, xpath, contextNode, resultType, namespaceResolver, resultObj) + { + var windowUnderTest, evaluator, isResultObjProvided, result; + + windowUnderTest = selenium.browserbot.getCurrentWindow(); + evaluator = doc || windowUnderTest.document; + contextNode = contextNode || evaluator; + resultType = resultType || XPathResult.ANY_TYPE; + isResultObjProvided = (resultObj != null); + + // The server can run tests against many different browsers. We have to + // feature test for document.evaluate in the context of the application + // under test. + if(typeof windowUnderTest.document.evaluate !== 'function') { + evaluator = document; + } + + $$.xp.logXpathEval(doc, xpath, contextNode); + try { + result = evaluator.evaluate( + xpath + , contextNode + , namespaceResolver + , resultType + , resultObj); + $$.LOG.trace("XPATH Result: " + $$.xp.fmtXpathResultType(result) + " : " + xpath); + } + catch (err) { + $$.LOG.error("XPATH: " + xpath); + //$$.LOG.traceback(err); + throw err; + } + if (isResultObjProvided) { + result = resultObj; + } + return result; + } + + // Find the first matching element + ,selectElement: function(doc, xpath, contextNode) { + var elems = $$.xp.selectElements(doc, xpath, contextNode); + return (elems && elems.length > 0 ? elems[0] : null); + } + + // Find all matching elements + // TBD: make XPath engine choice configurable + ,selectElements: function(doc, xpath, contextNode) { + var elems = $$.xp.selectNodes(doc, xpath, contextNode); + return elems; + } + + // Select a single node + // (analogous to xpath[1], without the axis-precedence gotchas) + ,selectNode: function(doc, xpath, contextNode, resultType) { + var result = $$.xp.evaluateXpath(doc, xpath, contextNode, resultType || XPathResult.FIRST_ORDERED_NODE_TYPE); + return $$.unwrapObject(result.singleNodeValue); + } + + // Select one or more nodes as an array + ,selectNodes: function(doc, xpath, contextNode, resultType) { + var result = $$.xp.evaluateXpath(doc, xpath, contextNode, resultType || XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + var nodes = []; + $$.xp.foreachNode(result, function (n, i) { + nodes.push($$.unwrapObject(n)); + }); + return nodes; + } + + // Select all matching nodes in the document, as a snapshot object + ,selectNodeSnapshot: function(doc, xpath, contextNode) { + return $$.xp.evaluateXpath(doc, xpath, contextNode, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + } + + // Select the exact matching node, else null + ,selectUniqueNodeNullable: function(doc, xpath, contextNode) + { + var nodeSet = $$.xp.selectNodeSnapshot(doc, xpath, contextNode); + if (!nodeSet || nodeSet.snapshotLength == 0) { + return null; + } + if (nodeSet.snapshotLength > 1) { + $$.LOG.debug("Ambiguous: " + nodeSet.snapshotLength + " matches"); + return null; + } + return $$.unwrapObject(nodeSet.snapshotItem(0)); + } + + // Select matching node as string/number/boolean value + // TBD: Exclude the text of certain node types (eg, script). + // A way to filter would be to add "//*[not(self::script)]/text()[normalize-space(.)!='']" + // But that yields a node set and XPath stringify operations only use the first node in a node set. + // Other invisibles: //*[contains(translate(@style,' ',''),'display:none') or contains(translate(@style,' ',''),'visibility:hidden')] + // (for inline styling at least, cascaded styling is not accessible via XPath) + ,selectValue: function(doc, xpath, contextNode) + { + var result = $$.xp.evaluateXpath(doc, xpath, contextNode, XPathResult.ANY_TYPE); + if (!result) + return null; + + var value = null; + switch (result.resultType) { + case result.STRING_TYPE: value = result.stringValue; break; + case result.NUMBER_TYPE: value = result.numberValue; break; + case result.BOOLEAN_TYPE: value = result.booleanValue; break; + } + return value; + } + + // Operate on each node in the given snapshot object + ,foreachNode: function(nodeSet, callbackFunc) + { + if (!nodeSet) + return; + var i = 0; + var n = nodeSet.snapshotItem(i); + while (n != null) { + var result = callbackFunc($$.unwrapObject(n), i); + if (result == false) { + return; // the callbackFunc can abort the loop by returning false + } + n = nodeSet.snapshotItem(++i); + } + } + + // Format an xpath result according to its data type + ,fmtXpathResultType: function(result) + { + if (!result) return null; + switch (result.resultType) { + case result.STRING_TYPE: return "'" + result.stringValue + "'"; + case result.NUMBER_TYPE: return result.numberValue; + case result.BOOLEAN_TYPE: return result.booleanValue; + case result.ANY_UNORDERED_NODE_TYPE: return "uNODE " + result.singleNodeValue; + case result.FIRST_ORDERED_NODE_TYPE: return "oNODE " + result.singleNodeValue; + case result.UNORDERED_NODE_SNAPSHOT_TYPE: return result.snapshotLength + " uNODEs"; + case result.ORDERED_NODE_SNAPSHOT_TYPE: return result.snapshotLength + " oNODEs"; + case result.UNORDERED_NODE_ITERATOR_TYPE: return "uITR"; + case result.ORDERED_NODE_ITERATOR_TYPE: return "oITR"; + } + return result; + } + + // Log an xpath result + ,logXpathEval: function(doc, xpath, contextNode) + { + $$.LOG.debug("XPATH: " + xpath); + if (contextNode && contextNode != doc) { + $$.LOG.debug("XPATH Context: " + contextNode); + } + } + }; + +}(selblocks)); +/** Parse basic expressions. +*/ +// selbocks name-space +(function($$){ + + $$.InfixExpressionParser = + { + _objname : "InfixExpressionParser" + ,BRACKET_PAIRS : { "(": ")", "{": "}", "[": "]" } + ,trimListValues : true + + //- Parse a string into a list on the given delimiter character, + // respecting embedded quotes and brackets + ,splitList : function(str, delim) + { + var values = []; + var prev = 0, cur = 0; + while (cur < str.length) { + if (str.charAt(cur) != delim) { + cur = this.spanSub(str, cur); + if (cur == -1) + throw new Error("Unbalanced expression grouping at: " + str.substr(prev)); + } + else { + var value = str.substring(prev, cur); + if (this.trimListValues) + value = value.trim(); + values.push(value); + prev = cur + 1; + } + cur++; + } + values.push(str.substring(prev)); + if (values.length == 1 && values[0].trim() == "") { + values.length = 0; + } + return values; + } + + //- Scan to the given chr, skipping over intervening matching brackets + ,spanTo : function(str, i, chr) + { + while (str.charAt(i) != chr) { + i = this.spanSub(str, i); + if (i == -1 || i >= str.length) + return -1; + i++; + } + return i; + } + + //- If character at the given index is a open/quote character, then scan to its matching close/quote + ,spanSub : function(str, i) + { + if (i < str.length) { + if (str.charAt(i) == "(") return this.spanTo(str, i+1, ")"); // recursively skip over intervening matching brackets + else if (str.charAt(i) == "[") return this.spanTo(str, i+1, "]"); + else if (str.charAt(i) == "{") return this.spanTo(str, i+1, "}"); + else if (str.charAt(i) == "'") return str.indexOf("'", i+1); // no special meaning for intervening brackets + else if (str.charAt(i) == '"') return str.indexOf('"', i+1); + } + return i; + } + + //- Format the given values array into a delimited list string + // An optional transformFunc operates on each value. + ,formatList : function(delim, values, left, transformFunc, right) + { + var buf = ""; + for (var i = 0; i < values.length; i++) { + var value = ((transformFunc) ? transformFunc(values[i], i) : values[i]); + if (buf) buf += delim || " "; + if (left) buf += left; + if (value) buf += value; + if (right) buf += right; + } + return buf; + } + }; + +}(selblocks)); +// selbocks name-space +(function($$){ + /* This function replaces native Selenium command handling for the exitScript command. + * (See TestLoop.prototype.resume() in chrome/content/selenium-core/scripts/selenium-executionloop.js.) + * This causes the script to simply halt rather continuing on to the next command. + */ + $$.handleAsExitTest = function() + { + try { + selenium.browserbot.runScheduledPollers(); + this.testComplete(); + } catch (e) { + // seems highly unlikely that there would be an error in this very simple case + this._handleCommandError(e); // marks command as failed (red), and overall test as failed + this.testComplete(); + } + $$.LOG.info("TEST HALTED"); + }; + +}(selblocks)); +// selbocks name-space +(function($$){ + /* This function replaces native Selenium command handling while inside a try block. + * (See TestLoop.prototype.resume() in chrome/content/selenium-core/scripts/selenium-executionloop.js.) + * Command processing is altered so that catch and/or finally processing is initiated upon error. + */ + $$.handleAsTryBlock = function() + { + try { + selenium.browserbot.runScheduledPollers(); + this._executeCurrentCommand(); + if (this.result.failed && isManaged(this.result)) { + // a failed verify command has activated catch/finally bubbling + this.continueTest(); + } + else { + // normal Selenium behavior + this.continueTestWhenConditionIsTrue(); + } + } catch (e) { + if (isManaged(e)) { + // a caught error has activated catch/finally bubbling + this.continueTest(); + } + else { + // normal Selenium behavior + if (!this._handleCommandError(e)) { + // command is marked in red, and overall test status is failed + this.testComplete(); + } else { + // error has been otherwise handled by TestLoop.prototype._handleCommandError() + // (not sure what the possibilities are, other than stopping and failing the script) + this.continueTest(); + } + } + } + + function isManaged(e) { + var interceptFrame = $$.fn.getInterceptTop(); + var out = false; + if (e.constructor.name == "AssertResult") { + e = new Error(e.failureMessage); + } + try { + out = (interceptFrame && interceptFrame.attrs.manageError(e)); + } catch (ignore) { + // if there was an error trying to see if the error is managed, + // then it is not managed. + } + return out; + } + }; + +}(selblocks)); +/* + * SelBlocks 2.0.2 + * + * Provides commands for Javascript-like looping and callable functions, + * with scoped variables, and JSON/XML driven parameterization. + * + * (SelBlocks installs as a Core Extension, not an IDE Extension, because it manipulates the Selenium object) + * + * Concept of operation: + * - Selenium.reset() is intercepted to initialize the block structures. + * - testCase.nextCommand() is overridden for flow branching. + * - TestLoop.resume() is overridden by exitTest, and by try/catch/finally to manage the outcome of errors. + * - The static structure of command blocks is stored in blockDefs[] by script line number. + * E.g., ifDef has pointers to its corresponding elseIf, else, endIf commands. + * - The state of each function-call is pushed/popped on callStack as it begins/ends execution + * The state of each block is pushed/popped on the blockStack as it begins/ends execution. + * An independent blockStack is associated with each function-call. I.e., stacks stored on a stack. + * (Non-block commands do not appear on the blockStack.) + * + * Limitations: + * - Incompatible with flowControl (and derivatives), because they unilaterally override selenium.reset(). + * Known to have this issue: + * selenium_ide__flow_control + * goto_while_for_ide + * + * Acknowledgements: + * SelBlocks reuses bits & parts of extensions: flowControl, datadriven, and include. + * + * Wishlist: + * - show line numbers in the IDE + * - validation of JSON & XML input files + * - highlight a command that is failed-but-caught in blue + * + * Changes since 1.5: + * - added try/catch/finally, elseIf, and exitTest commands + * - block boundaries enforced (jumping in-to and/or out-of the middle of blocks) + * - script/endScript is replaced by function/endFunction + * - implicit initialization of for loop variable(s) + * - improved validation of command expressions + * + * NOTE - The only thing special about SelBlocks parameters is that they are activated and deactivated + * as script execution flows into and out of blocks, (for/endFor, function/endFunction, etc). + * They are implemented as regular Selenium variables, and therefore the progress of an executing + * script can be monitored using the Stored Variables Viewer addon. + */ + +// =============== global functions as script helpers =============== +// getEval script helpers + +// Find an element via locator independent of any selenium commands +// (findElementOrNull returns the first if there are multiple matches) +function $e(locator) { + return selblocks.unwrapObject(selenium.browserbot.findElementOrNull(locator)); +} + +// Return the singular XPath result as a value of the appropriate type +function $x(xpath, contextNode, resultType) { + var doc = selenium.browserbot.getDocument(); + var node; + if (resultType) { + node = selblocks.xp.selectNode(doc, xpath, contextNode, resultType); // mozilla engine only + } + else { + node = selblocks.xp.selectElement(doc, xpath, contextNode); + } + return node; +} + +// Return the XPath result set as an array of elements +function $X(xpath, contextNode, resultType) { + var doc = selenium.browserbot.getDocument(); + var nodes; + if (resultType) { + nodes = selblocks.xp.selectNodes(doc, xpath, contextNode, resultType); // mozilla engine only + } + else { + nodes = selblocks.xp.selectElements(doc, xpath, contextNode); + } + return nodes; +} + +// selbocks name-space +(function($$){ + // =============== Javascript extensions as script helpers =============== + // EXTENSION REVIEWERS: + // Global functions are intentional features provided for use by end user's in their Selenium scripts. + + // eg: "dilbert".isOneOf("dilbert","dogbert","mordac") => true + String.prototype.isOneOf = function(valuesObj) + { + var values = valuesObj; + if (!(values instanceof Array)) { + // copy function arguments into an array + values = Array.prototype.slice.call(arguments); + } + var i; + for (i = 0; i < this.length; i++) { + if (values[i] == this) { + return true; + } + } + return false; + }; + + // eg: "red".mapTo("primary", ["red","green","blue"]) => primary + String.prototype.mapTo = function(/* pairs of: string, array */) + { + var errMsg = " The map function requires pairs of argument: string, array"; + assert(arguments.length % 2 === 0, errMsg + "; found " + arguments.length); + var i; + for (i = 0; i < arguments.length; i += 2) { + assert((typeof arguments[i].toLowerCase() === "string") && (arguments[i+1] instanceof Array), + errMsg + "; found " + typeof arguments[i] + ", " + typeof arguments[i+1]); + if (this.isOneOf(arguments[i+1])) { + return arguments[i]; + } + } + return this; + }; + + // Return a translated version of a string + // given string args, translate each occurrence of characters in t1 with the corresponding character from t2 + // given array args, if the string occurs in t1, return the corresponding string from t2, else null + String.prototype.translate = function(t1, t2) + { + assert(t1.constructor === t2.constructor, "translate() function requires arrays of the same type"); + assert(t1.length === t2.length, "translate() function requires arrays of equal size"); + var i; + if (t1.constructor === String) { + var buf = ""; + for (i = 0; i < this.length; i++) { + var c = this.substr(i,1); + var t; + for (t = 0; t < t1.length; t++) { + if (c === t1.substr(t,1)) { + c = t2.substr(t,1); + break; + } + } + buf += c; + } + return buf; + } + + if (t1.constructor === Array) { + for (i = 0; i < t1.length; i++) { + if (t1[i] == this) { + return t2[i]; + } + } + } + else { + assert(false, "translate() function requires arguments of type String or Array"); + } + return null; + }; + + //=============== Call/Scope Stack handling =============== + + var symbols = {}; // command indexes stored by name: function names + var blockDefs = null; // static command definitions stored by command index + var callStack = null; // command execution stack + var contextManager; // makes block scoped variables work + // intentionally global var + storedVarsGlobal = storedVars; + /** + * Manages variable scope for functions, blocks, etc. + * @class ContextManager + */ + function ContextManager() { + // intentionally global var + storedVarsLocal = Object.create(storedVarsGlobal); + storedVars = storedVarsLocal; + this.contexts = []; + this.enter(); + } + /** + * Enters a new variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.enter = function enterContext() { + var _o = storedVars; + var context = { + here : Object.create(storedVars), + back : _o + }; + this.contexts.push(context); + storedVars = context.here; + storedVarsLocal = context.here; + }; + /** + * Exits to the previous variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.exit = function exitContext() { + if (this.contexts.length > 0) { + var context = this.contexts.pop(); + storedVars = context.back; + storedVarsLocal = context.back; + } else { + throw new Error("No context to exit from"); + } + }; + /** + * Resets to the top variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.reset = function exitContext() { + storedVars = storedVarsGlobal; + build_sendkeys_maps(); + storedVarsLocal = storedVarsGlobal; + this.contexts = []; + this.enter(); + }; + /** + * Stores variable into the context chain in the last parent where it was + * defined. This allows values to bubble up to their relevant parent so that + * you don't have to pass everything in global scope. The variable must exist + * in a parent scope in order to be caught there, otherwise it will get to + * the global scope and be set there. + * @param {String} propName The name of the variable. + * @param {Mixed} val Any value you could set for a variable. + */ + ContextManager.prototype.storeAtClosestContextWithPropName = + function storeAtClosestContextWithPropName (propName, val) { + var out = undefined; + var idx = this.contexts.length - 1; + while (idx >= 0 && out === undefined) { + if(this.contexts[idx].here.hasOwnProperty(propName)) { + this.contexts[idx].here[String(propName)] = val; + out = true; + } + idx--; + } + if(out === undefined) { + storedVarsGlobal[String(propName)] = val; + $$.LOG.warn(String(propName) + " not found, setting global variable"); + } + }; + contextManager = new ContextManager(); + /** + * State information about the cache. + * currentCaseTitle is the current case displayed in the UI + * activeCaseTitle is the cashed case where commands are actually being pulled + * from. + * commandIndex is the current index of the commands array in the active case + * suites are the cached test suites commands, symbols, and blockDefs + */ + var cachedCommandsData = { + initializing : true, + currentCaseTitle : '', + activeCaseTitle : '', + commandIndex : 0, + suites : Object.create(null), + /** + * Caches information about the current test case + */ + cacheCommands : function cacheCacheCommands(symbols, commands, blockDefs) { + cachedCommandsData.initializing = false; + cachedCommandsData.suites[cachedCommandsData.currentCaseTitle] = { + 'symbols' : symbols, + 'commands' : commands, + 'blockDefs' : blockDefs + } + }, + /** + * Starts a new suite cache. + */ + init : function cacheInit() { + cachedCommandsData.initializing = true; + var _mytitle; + if(globalContext.onServer === true) { + _mytitle = testCase.htmlTestCase.testDocument.title || "untitiled"; + } else { + _mytitle = testCase.title || "untitiled"; + } + // the current case displayed in the IDE + cachedCommandsData.currentCaseTitle = String(_mytitle); + // the current case for looking up functions + cachedCommandsData.activeCaseTitle = String(_mytitle); + // the index used for executing commands, this is decoupled from the + // testCase.debugIndex because what's being executed doesn't always + // move the row cursor in the UI anymore. + cachedCommandsData.commandIndex = 0; + } + }; + + // the idx of the currently executing command + function idxHere() { + return cachedCommandsData.commandIndex; + } + + // Command structure definitions, stored by command index + function BlockDefs() { + var blkDefs = []; + // initialize blockDef at the given command index + blkDefs.init = function(i, attrs) { + blkDefs[i] = attrs || {}; + blkDefs[i].idx = i; + blkDefs[i].cmdName = testCase.commands[i].command; + return blkDefs[i]; + }; + return blkDefs; + } + + // retrieve the blockDef at the given command idx + function blkDefAt(idx) { + var where; + if(cachedCommandsData.initializing === true) { + where = blockDefs[idx]; + } else { + where = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].blockDefs[idx]; + } + return where; + } + // retrieve the blockDef for the currently executing command + function blkDefHere() { + return blkDefAt(idxHere()); + } + // retrieve the blockDef for the given blockDef frame + function blkDefFor(stackFrame) { + if (!stackFrame) { + return null; + } + return blkDefAt(stackFrame.idx); + } + + // An Array object with stack functionality + function Stack() { + var stack = []; + stack.isEmpty = function() { return stack.length === 0; }; + stack.top = function() { return stack[stack.length-1]; }; + stack.findEnclosing = function(_hasCriteria) { return stack[stack.indexWhere(_hasCriteria)]; }; + stack.indexWhere = function(_hasCriteria) { // undefined if not found + var i; + for (i = stack.length-1; i >= 0; i--) { + if (_hasCriteria(stack[i])) { + return i; + } + } + }; + stack.unwindTo = function(_hasCriteria) { + if (stack.length === 0) { + return null; + } + while (!_hasCriteria(stack.top())) { + stack.pop(); + } + return stack.top(); + }; + stack.isHere = function() { + return (stack.length > 0 && stack.top().idx === idxHere()); + }; + return stack; + } + + // Determine if the given stack frame is one of the given block kinds + Stack.isTryBlock = function(stackFrame) { return (blkDefFor(stackFrame).nature === "try"); }; + Stack.isLoopBlock = function(stackFrame) { return (blkDefFor(stackFrame).nature === "loop"); }; + Stack.isFunctionBlock = function(stackFrame) { return (blkDefFor(stackFrame).nature === "function"); }; + + + // Flow control - we don't just alter debugIndex on the fly, because the command + // preceding the destination would falsely get marked as successfully executed + var branchIdx = null; + // if testCase.nextCommand() ever changes, this will need to be revisited + // (current as of: selenium-ide-2.4.0) + function nextCommand() { + if (!this.started) { + this.started = true; + this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; + cachedCommandsData.commandIndex = 0 + this.debugIndex; + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); + } + else { + if (branchIdx !== null) { + $$.LOG.info("branch => " + fmtCmdRef(branchIdx)); + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex = branchIdx; + } + cachedCommandsData.commandIndex = branchIdx; + branchIdx = null; + } + else { + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex++; + } + cachedCommandsData.commandIndex++; + } + } + + var command; + // skip over comments + while (cachedCommandsData.commandIndex < cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands.length) { + command = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands[cachedCommandsData.commandIndex]; + + if(globalContext.onServer === true) { + this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + command = this.currentRow.getCommand(); + command.type = "command"; + } + if (this.sejsElement) { + this.currentItem = agenda.pop(); + this.currentRowIndex = this.debugIndex; + } + } + + if (command.type === "command") { + this.runTimeStamp = Date.now(); + return command; + } + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex++; + } + cachedCommandsData.commandIndex++; + } + + if(globalContext.onServer === true) { + this.currentRow = null; + this.currentItem = null; + } + return null; + } + /** + * Creates a pointer to the next command to execute. This pointer is used by + * nextCommand when considering what to do next. + * @param {Number} cmdIdx The index of the next command to execute. + */ + function setNextCommand(cmdIdx) { + assert(cmdIdx >= 0 && cmdIdx < cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands.length, + " Cannot branch to non-existent command " + String(cachedCommandsData.activeCaseTitle) + " @" + (cmdIdx+1)); + branchIdx = cmdIdx; + } + // Selenium calls reset(): + // * before each single (double-click) command execution + // * before a testcase is run + // * before each testcase runs in a running testsuite + // TBD: skip during single command execution + $$.fn.interceptAfter(Selenium.prototype, "reset", function() + { + $$.LOG.trace("In tail intercept :: Selenium.reset()"); + try { + contextManager.reset(); + compileSelBlocks(); + } + catch (err) { + notifyFatalErr("In " + err.fileName + " @" + err.lineNumber + ": " + err); + } + callStack = new Stack(); + callStack.push({ blockStack: new Stack() }); // top-level execution state + + $$.tcf = { nestingLevel: -1 }; // try/catch/finally nesting + + // customize flow control logic + // TBD: this should be a tail intercept rather than brute force replace + $$.LOG.debug("Configuring tail intercept: testCase.debugContext.nextCommand()"); + $$.fn.interceptReplace(testCase.debugContext, "nextCommand", nextCommand); + }); + + /** + * gets the blockStack for the currently active callStack + */ + function activeBlockStack() { + return callStack.top().blockStack; + } + + // ================================================================================ + /** + * Assembles block relationships and symbol locations. + */ + function compileSelBlocks() + { + cachedCommandsData.init(); + symbols = {}; + blockDefs = new BlockDefs(); + var lexStack = new Stack(); + var i; + for (i = 0; i < testCase.commands.length; i++) + { + if (testCase.commands[i].type === "command") + { + var curCmd = testCase.commands[i].command; + var aw = curCmd.indexOf("AndWait"); + if (aw !== -1) { + // just ignore the suffix for now, this may or may not be a SelBlocks commands + curCmd = curCmd.substring(0, aw); + } + var cmdTarget = testCase.commands[i].target; + + var ifDef; + var tryDef; + var expectedCmd; + switch(curCmd) + { + case "label": + assertNotAndWaitSuffix(i); + symbols[cmdTarget] = i; + break; + case "goto": case "gotoIf": case "skipNext": + assertNotAndWaitSuffix(i); + break; + + case "if": + assertNotAndWaitSuffix(i); + lexStack.push(blockDefs.init(i, { nature: "if", elseIfIdxs: [] })); + break; + case "elseIf": + assertNotAndWaitSuffix(i); + assertBlockIsPending("elseIf", i, ", is not valid outside of an if/endIf block"); + ifDef = lexStack.top(); + assertMatching(ifDef.cmdName, "if", i, ifDef.idx); + var eIdx = blkDefFor(ifDef).elseIdx; + if (eIdx) { + notifyFatal(fmtCmdRef(eIdx) + " An else has to come after all elseIfs."); + } + blockDefs.init(i, { ifIdx: ifDef.idx }); // elseIf -> if + blkDefFor(ifDef).elseIfIdxs.push(i); // if -> elseIf(s) + break; + case "else": + assertNotAndWaitSuffix(i); + assertBlockIsPending("if", i, ", is not valid outside of an if/endIf block"); + ifDef = lexStack.top(); + assertMatching(ifDef.cmdName, "if", i, ifDef.idx); + if (blkDefFor(ifDef).elseIdx) { + notifyFatal(fmtCmdRef(i) + " There can only be one else associated with a given if."); + } + blockDefs.init(i, { ifIdx: ifDef.idx }); // else -> if + blkDefFor(ifDef).elseIdx = i; // if -> else + break; + case "endIf": + assertNotAndWaitSuffix(i); + assertBlockIsPending("if", i); + ifDef = lexStack.pop(); + assertMatching(ifDef.cmdName, "if", i, ifDef.idx); + blockDefs.init(i, { ifIdx: ifDef.idx }); // endIf -> if + blkDefFor(ifDef).endIdx = i; // if -> endif + if (ifDef.elseIdx) { + blkDefAt(ifDef.elseIdx).endIdx = i; // else -> endif + } + break; + + case "try": + assertNotAndWaitSuffix(i); + lexStack.push(blockDefs.init(i, { nature: "try", name: cmdTarget })); + break; + case "catch": + assertNotAndWaitSuffix(i); + assertBlockIsPending("try", i, ", is not valid without a try block"); + tryDef = lexStack.top(); + assertMatching(tryDef.cmdName, "try", i, tryDef.idx); + if (blkDefFor(tryDef).catchIdx) { + notifyFatal(fmtCmdRef(i) + " There can only be one catch-block associated with a given try."); + } + var fIdx = blkDefFor(tryDef).finallyIdx; + if (fIdx) { + notifyFatal(fmtCmdRef(fIdx) + " A finally-block has to be last in a try section."); + } + blockDefs.init(i, { tryIdx: tryDef.idx }); // catch -> try + blkDefFor(tryDef).catchIdx = i; // try -> catch + break; + case "finally": + assertNotAndWaitSuffix(i); + assertBlockIsPending("try", i); + tryDef = lexStack.top(); + assertMatching(tryDef.cmdName, "try", i, tryDef.idx); + if (blkDefFor(tryDef).finallyIdx) { + notifyFatal(fmtCmdRef(i) + " There can only be one finally-block associated with a given try."); + } + blockDefs.init(i, { tryIdx: tryDef.idx }); // finally -> try + blkDefFor(tryDef).finallyIdx = i; // try -> finally + if (tryDef.catchIdx) { + blkDefAt(tryDef.catchIdx).finallyIdx = i; // catch -> finally + } + break; + case "endTry": + assertNotAndWaitSuffix(i); + assertBlockIsPending("try", i); + tryDef = lexStack.pop(); + assertMatching(tryDef.cmdName, "try", i, tryDef.idx); + if (cmdTarget) { + assertMatching(tryDef.name, cmdTarget, i, tryDef.idx); // pair-up on try-name + } + blockDefs.init(i, { tryIdx: tryDef.idx }); // endTry -> try + blkDefFor(tryDef).endIdx = i; // try -> endTry + if (tryDef.catchIdx) { + blkDefAt(tryDef.catchIdx).endIdx = i; // catch -> endTry + } + break; + + case "while": case "for": case "foreach": case "forJson": case "forXml": + assertNotAndWaitSuffix(i); + lexStack.push(blockDefs.init(i, { nature: "loop" })); + break; + case "continue": case "break": + assertNotAndWaitSuffix(i); + assertCmd(i, lexStack.findEnclosing(Stack.isLoopBlock), ", is not valid outside of a loop"); + blockDefs.init(i, { beginIdx: lexStack.top().idx }); // -> begin + break; + case "endWhile": case "endFor": case "endForeach": case "endForJson": case "endForXml": + assertNotAndWaitSuffix(i); + expectedCmd = curCmd.substr(3).toLowerCase(); + assertBlockIsPending(expectedCmd, i); + var beginDef = lexStack.pop(); + assertMatching(beginDef.cmdName.toLowerCase(), expectedCmd, i, beginDef.idx); + blkDefFor(beginDef).endIdx = i; // begin -> end + blockDefs.init(i, { beginIdx: beginDef.idx }); // end -> begin + break; + + case "loadJsonVars": case "loadXmlVars": + assertNotAndWaitSuffix(i); + break; + + case "call": + assertNotAndWaitSuffix(i); + blockDefs.init(i); + break; + case "function": case "script": + assertNotAndWaitSuffix(i); + symbols[cmdTarget] = i; + lexStack.push(blockDefs.init(i, { nature: "function", name: cmdTarget })); + break; + case "return": + assertNotAndWaitSuffix(i); + assertBlockIsPending("function", i, ", is not valid outside of a function/endFunction block"); + var funcCmd = lexStack.findEnclosing(Stack.isFunctionBlock); + blockDefs.init(i, { funcIdx: funcCmd.idx }); // return -> function + break; + case "endFunction": case "endScript": + assertNotAndWaitSuffix(i); + expectedCmd = curCmd.substr(3).toLowerCase(); + assertBlockIsPending(expectedCmd, i); + var funcDef = lexStack.pop(); + assertMatching(funcDef.cmdName.toLowerCase(), expectedCmd, i, funcDef.idx); + if (cmdTarget) { + assertMatching(funcDef.name, cmdTarget, i, funcDef.idx); // pair-up on function name + } + blkDefFor(funcDef).endIdx = i; // function -> endFunction + blockDefs.init(i, { funcIdx: funcDef.idx }); // endFunction -> function + break; + + case "exitTest": + assertNotAndWaitSuffix(i); + break; + default: + } + } + } + if (!lexStack.isEmpty()) { + // unterminated block(s) + var cmdErrors = []; + while (!lexStack.isEmpty()) { + var pend = lexStack.pop(); + cmdErrors.unshift(fmtCmdRef(pend.idx) + " without a terminating " + + "'end" + pend.cmdName.substr(0, 1).toUpperCase() + pend.cmdName.substr(1) + "'" + ); + } + throw new SyntaxError(cmdErrors.join("; ")); + } + cachedCommandsData.cacheCommands(symbols, testCase.commands, blockDefs); + //- command validation + function assertNotAndWaitSuffix(cmdIdx) { + assertCmd(cmdIdx, (testCase.commands[cmdIdx].command.indexOf("AndWait") === -1), + ", AndWait suffix is not valid for SelBlocks commands"); + } + //- active block validation + function assertBlockIsPending(expectedCmd, cmdIdx, desc) { + assertCmd(cmdIdx, !lexStack.isEmpty(), desc || ", without an beginning [" + expectedCmd + "]"); + } + //- command-pairing validation + function assertMatching(curCmd, expectedCmd, cmdIdx, pendIdx) { + assertCmd(cmdIdx, curCmd === expectedCmd, ", does not match command " + fmtCmdRef(pendIdx)); + } + } + + // -------------------------------------------------------------------------------- + + /** + * prevents jumping in-to and/or out-of loop/function/try blocks + */ + function assertIntraBlockJumpRestriction(fromIdx, toIdx) { + var fromRange = findBlockRange(fromIdx); + var toRange = findBlockRange(toIdx); + if (fromRange || toRange) { + var msg = " Attempt to jump"; + if (fromRange) { msg += " out of " + fromRange.desc + fromRange.fmt(); } + if (toRange) { msg += " into " + toRange.desc + toRange.fmt(); } + assert(fromRange && fromRange.equals(toRange), msg + + ". You cannot jump into, or out of: loops, functions, or try blocks."); + } + } + + /** + * ascertain in which, if any, block that an locusIdx occurs + */ + function findBlockRange(locusIdx) { + var idx; + for (idx = locusIdx-1; idx >= 0; idx--) { + var blk = blkDefAt(idx); + if (blk) { + if (locusIdx > blk.endIdx) { // ignore blocks that are inside this same block + continue; + } + switch (blk.nature) { + case "loop": return new CmdRange(blk.idx, blk.endIdx, blk.cmdName + " loop"); + case "function": return new CmdRange(blk.idx, blk.endIdx, "function '" + blk.name + "'"); + case "try": return isolateTcfRange(locusIdx, blk); + } + } + } + // return as undefined (no enclosing block at all) + } + + // pin-point in which sub-block, (try, catch or finally), that the idx occurs + function isolateTcfRange(idx, tryDef) { + // assumptions: idx is known to be between try & endTry, and catch always precedes finally + var RANGES = [ + { ifr: tryDef.finallyIdx, ito: tryDef.endIdx, desc: "finally", desc2: "end" } + ,{ ifr: tryDef.catchIdx, ito: tryDef.finallyIdx, desc: "catch", desc2: "finally" } + ,{ ifr: tryDef.catchIdx, ito: tryDef.endIdx, desc: "catch", desc2: "end" } + ,{ ifr: tryDef.idx, ito: tryDef.catchIdx, desc: "try", desc2: "catch" } + ,{ ifr: tryDef.idx, ito: tryDef.finallyIdx, desc: "try", desc2: "finally" } + ,{ ifr: tryDef.idx, ito: tryDef.endIdx, desc: "try", desc2: "end" } + ]; + var i; + for (i = 0; i < RANGES.length; i++) { + var rng = RANGES[i]; + if (rng.ifr <= idx && idx < rng.ito) { + var desc = rng.desc + "-block"; + if (rng.desc !== "try") { desc += " for"; } + if (tryDef.name) { desc += " '" + tryDef.name + "'"; } + return new CmdRange(rng.ifr, rng.ito, desc); + } + } + } + + // represents a range of script lines + function CmdRange(topIdx, bottomIdx, desc) { + this.topIdx = topIdx; + this.bottomIdx = bottomIdx; + this.desc = desc; + this.equals = function(cmdRange) { + return (cmdRange && cmdRange.topIdx === this.topIdx && cmdRange.bottomIdx === this.bottomIdx); + }; + this.fmt = function() { + return " @[" + (this.topIdx+1) + "-" + (this.bottomIdx+1) + "]"; + }; + } + + // ==================== SelBlocks Commands (Custom Selenium Actions) ==================== + + var iexpr = Object.create($$.InfixExpressionParser); + + // validate variable/parameter names + function validateNames(names, desc) { + var i; + for (i = 0; i < names.length; i++) { + validateName(names[i], desc); + } + } + function validateName(name, desc) { + var match = name.match(/^[a-zA-Z]\w*$/); + if (!match) { + notifyFatal("Invalid character(s) in " + desc + " name: '" + name + "'"); + } + } + + Selenium.prototype.doLabel = function() { + // noop + }; + + // Skip the next N commands (default is 1) + Selenium.prototype.doSkipNext = function(spec) + { + assertRunning(); + var n = parseInt(evalWithVars(spec), 10); + if (isNaN(n)) { + if (spec.trim() === "") { n = 1; } + else { notifyFatalHere(" Requires a numeric value"); } + } + else if (n < 0) { + notifyFatalHere(" Requires a number > 1"); + } + + if (n !== 0) { // if n=0, execute the next command as usual + destIdx = idxHere() + n + 1; + assertIntraBlockJumpRestriction(idxHere(), destIdx); + setNextCommand(destIdx); + } + }; + + Selenium.prototype.doGoto = function(label) + { + assertRunning(); + assert(symbols[label]!==undefined, " Target label '" + label + "' is not found."); + assertIntraBlockJumpRestriction(idxHere(), symbols[label]); + setNextCommand(symbols[label]); + }; + + Selenium.prototype.doGotoIf = function(condExpr, label) + { + assertRunning(); + if (evalWithVars(condExpr)) { + this.doGoto(label); + } + }; + + // ================================================================================ + Selenium.prototype.doIf = function(condExpr, locator) + { + assertRunning(); + var ifDef = blkDefHere(); + var ifState = { idx: idxHere(), elseIfItr: arrayIterator(ifDef.elseIfIdxs) }; + activeBlockStack().push(ifState); + cascadeElseIf(ifState, condExpr); + }; + Selenium.prototype.doElseIf = function(condExpr) + { + assertRunning(); + assertActiveScope(blkDefHere().ifIdx); + var ifState = activeBlockStack().top(); + if (ifState.skipElseBlocks) { // if, or previous elseIf, has already been met + setNextCommand(blkDefAt(blkDefHere().ifIdx).endIdx); + } + else { + cascadeElseIf(ifState, condExpr); + } + }; + Selenium.prototype.doElse = function() + { + assertRunning(); + assertActiveScope(blkDefHere().ifIdx); + var ifState = activeBlockStack().top(); + if (ifState.skipElseBlocks) { // if, or previous elseIf, has already been met + setNextCommand(blkDefHere().endIdx); + } + // else continue into else-block + }; + Selenium.prototype.doEndIf = function() { + assertRunning(); + assertActiveScope(blkDefHere().ifIdx); + activeBlockStack().pop(); + // fall out of if-endIf + }; + + function cascadeElseIf(ifState, condExpr) { + assertCompilable("", condExpr, ";", "Invalid condition"); + if (!evalWithVars(condExpr)) { + // jump to next elseIf or else or endif + var ifDef = blkDefFor(ifState); + if (ifState.elseIfItr.hasNext()) { setNextCommand(ifState.elseIfItr.next()); } + else if (ifDef.elseIdx) { setNextCommand(ifDef.elseIdx); } + else { setNextCommand(ifDef.endIdx); } + } + else { + ifState.skipElseBlocks = true; + // continue into if/elseIf block + } + } + + // ================================================================================ + + // throw the given Error + Selenium.prototype.doThrow = function(err) { + err = evalWithVars(err); + if (!(err instanceof Error)) { + err = new SelblocksError(idxHere(), err); + } + throw err; + }; + + // TBD: failed locators/timeouts/asserts ? + Selenium.prototype.doTry = function(tryName) + { + assertRunning(); + var tryState = { idx: idxHere(), name: tryName }; + activeBlockStack().push(tryState); + var tryDef = blkDefHere(); + + if (!tryDef.catchIdx && !tryDef.finallyIdx) { + $$.LOG.warn(fmtCurCmd() + " does not have a catch-block nor a finally-block, and therefore serves no purpose"); + if ($$.tcf.nestingLevel === -1) { + return; // continue into try-block without any special error handling + } + } + + // log an advisory about the active catch block + if (tryDef.catchIdx) { + var errDcl = testCase.commands[tryDef.catchIdx].target; + $$.LOG.debug(tryName + " catchable: " + (errDcl || "ANY")); + } + + $$.tcf.nestingLevel++; + tryState.execPhase = "trying"; + + if ($$.tcf.nestingLevel === 0) { + // enable special command handling + if(globalContext.onServer === true) { + $$.fn.interceptPush(htmlTestRunner.currentTest, "resume", + $$.handleAsTryBlock, { manageError: handleCommandError }); + } else { + $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", + $$.handleAsTryBlock, { manageError: handleCommandError }); + } + } + $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); + // continue into try-block + }; + + Selenium.prototype.doCatch = function() + { + assertRunning(); + assertActiveScope(blkDefHere().tryIdx); + var tryState = activeBlockStack().top(); + if (tryState.execPhase !== "catching") { + // skip over unused catch-block + var tryDef = blkDefFor(tryState); + if (tryDef.finallyIdx) { + setNextCommand(tryDef.finallyIdx); + } + else { + setNextCommand(tryDef.endIdx); + } + } + $$.LOG.debug("entering catch block"); + // else continue into catch-block + }; + Selenium.prototype.doFinally = function() { + assertRunning(); + assertActiveScope(blkDefHere().tryIdx); + delete storedVars._error; + $$.LOG.debug("entering finally block"); + // continue into finally-block + }; + Selenium.prototype.doEndTry = function(tryName) + { + assertRunning(); + assertActiveScope(blkDefHere().tryIdx); + delete storedVars._error; + var tryState = activeBlockStack().pop(); + if (tryState.execPhase) { // ie, it DOES have a catch and/or a finally block + $$.tcf.nestingLevel--; + $$.LOG.debug("-- try nesting: " + $$.tcf.nestingLevel); + if ($$.tcf.nestingLevel < 0) { + // discontinue try-block handling + $$.fn.interceptPop(); + // $$.tcf.bubbling = null; + } + if ($$.tcf.bubbling) { + reBubble(); + } + else { + $$.LOG.debug("no bubbling in process"); + } + } + var tryDef = blkDefFor(tryState); + $$.LOG.debug("end of try '" + tryDef.name + "'"); + // fall out of endTry + }; + + // -------------------------------------------------------------------------------- + + // alter the behavior of Selenium error handling + // returns true if catch/finally bubbling is active + function handleCommandError(err) + { + var tryState = bubbleToTryBlock(Stack.isTryBlock); + var tryDef = blkDefFor(tryState); + if (tryState) { + $$.LOG.debug("error encountered while: " + tryState.execPhase); + if (hasUnspentCatch(tryState)) { + if (isMatchingCatch(err, tryDef.catchIdx)) { + // an expected kind of error has been caught + $$.LOG.info("@" + (idxHere()+1) + ", error has been caught" + fmtCatching(tryState)); + tryState.hasCaught = true; + tryState.execPhase = "catching"; + storedVars._error = err; + $$.tcf.bubbling = null; + setNextCommand(tryDef.catchIdx); + return true; + } + } + } + // error not caught .. instigate bubbling + $$.LOG.debug("error not caught, bubbling error: '" + err.message + "'"); + $$.tcf.bubbling = { mode: "error", error: err, srcIdx: idxHere() }; + if (hasUnspentFinally(tryState)) { + $$.LOG.info("Bubbling suspended while finally block runs"); + tryState.execPhase = "finallying"; + tryState.hasFinaled = true; + setNextCommand(tryDef.finallyIdx); + return true; + } + if ($$.tcf.nestingLevel > 0) { + $$.LOG.info("No further handling, error bubbling will continue outside of this try."); + setNextCommand(tryDef.endIdx); + return true; + } + $$.LOG.info("No handling provided in this try section for this error: '" + err.message + "'"); + return false; // stop test + } + + // execute any enclosing finally block(s) until reaching the given type of enclosing block + function bubbleCommand(cmdIdx, _isContextBlockType) + { + var tryState = bubbleToTryBlock(isTryWithMatchingOrFinally); + var tryDef = blkDefFor(tryState); + $$.tcf.bubbling = { mode: "command", srcIdx: cmdIdx, _isStopCriteria: _isContextBlockType }; + if (hasUnspentFinally(tryState)) { + $$.LOG.info("Command " + fmtCmdRef(cmdIdx) + ", suspended while finally block runs"); + tryState.execPhase = "finallying"; + tryState.hasFinaled = true; + setNextCommand(tryDef.finallyIdx); + // begin finally block + } + else { + $$.LOG.info("No further handling, bubbling continuing outside of this try."); + setNextCommand(tryDef.endIdx); + // jump out of try section + } + + //- determine if catch matches an error, or there is a finally, or the ceiling block has been reached + function isTryWithMatchingOrFinally(stackFrame) { + if (_isContextBlockType && _isContextBlockType(stackFrame)) { + return true; + } + if ($$.tcf.bubbling && $$.tcf.bubbling.mode === "error" && hasUnspentCatch(stackFrame)) { + var tryDef = blkDefFor(stackFrame); + if (isMatchingCatch($$.tcf.bubbling.error, tryDef.catchIdx)) { + return true; + } + } + return hasUnspentFinally(stackFrame); + } + } + + //- error message matcher + function isMatchingCatch(e, catchIdx) { + var errDcl = testCase.commands[catchIdx].target; + if (!errDcl) { + return true; // no error specified means catch all errors + } + var errExpr = evalWithVars(errDcl); + var errMsg = e.message; + if (errExpr instanceof RegExp) { + return (errMsg.match(errExpr)); + } + return (errMsg.indexOf(errExpr) !== -1); + } + + // unwind the blockStack, and callStack (ie, aborting functions), until reaching the given criteria + function bubbleToTryBlock(_hasCriteria) { + if ($$.tcf.nestingLevel < 0) { + $$.LOG.warn("bubbleToTryBlock() called outside of any try nesting"); + } + var tryState = unwindToBlock(_hasCriteria); + var ret; + while (!tryState && $$.tcf.nestingLevel > -1 && callStack.length > 1) { + var callFrame = callStack.pop(); + $$.LOG.info("function '" + callFrame.name + "' aborting due to error"); + if (storedVars._result) { ret = storedVars._result; } + contextManager.exit(); + storedVars._result = ret; + //restoreVarState(callFrame.savedVars); + tryState = unwindToBlock(_hasCriteria); + } + return tryState; + } + + // unwind the blockStack until reaching the given criteria + function unwindToBlock(_hasCriteria) { + var tryState = activeBlockStack().unwindTo(_hasCriteria); + if (tryState) { + $$.LOG.debug("unwound to: " + fmtTry(tryState)); + } + return tryState; + } + + // resume or conclude command/error bubbling + function reBubble() { + if ($$.tcf.bubbling.mode === "error") { + if ($$.tcf.nestingLevel > -1) { + $$.LOG.debug("error-bubbling continuing..."); + handleCommandError($$.tcf.bubbling.error); + } + else { + $$.LOG.error("Error was not caught: '" + $$.tcf.bubbling.error.message + "'"); + try { throw $$.tcf.bubbling.error; } + finally { $$.tcf.bubbling = null; } + } + } + else { // mode == "command" + if (isBubblable()) { + $$.LOG.debug("command-bubbling continuing..."); + bubbleCommand($$.tcf.bubbling.srcIdx, $$.tcf.bubbling._isStopCriteria); + } + else { + $$.LOG.info("command-bubbling complete - suspended command executing now " + fmtCmdRef($$.tcf.bubbling.srcIdx)); + setNextCommand($$.tcf.bubbling.srcIdx); + $$.tcf.bubbling = null; + } + } + } + + // instigate or transform bubbling, as appropriate + function transitionBubbling(_isContextBlockType) + { + if ($$.tcf.bubbling) { // transform bubbling + if ($$.tcf.bubbling.mode === "error") { + $$.LOG.debug("Bubbling error: '" + $$.tcf.bubbling.error.message + "'" + + ", replaced with command " + fmtCmdRef(idxHere())); + $$.tcf.bubbling = { mode: "command", srcIdx: idxHere(), _isStopCriteria: _isContextBlockType }; + return true; + } + // mode == "command" + $$.LOG.debug("Command suspension " + fmtCmdRef($$.tcf.bubbling.srcIdx) + + ", replaced with " + fmtCmdRef(idxHere())); + $$.tcf.bubbling.srcIdx = idxHere(); + return true; + } + if (isBubblable(_isContextBlockType)) { // instigate bubbling + bubbleCommand(idxHere(), _isContextBlockType); + return true; + } + // no change to bubbling + return false; + } + + // determine if bubbling is possible from this point outward + function isBubblable(_isContextBlockType) { + var canBubble = ($$.tcf.nestingLevel > -1); + if (canBubble) { + var blkState = activeBlockStack().findEnclosing(isTryOrContextBlockType); + return (blkDefFor(blkState).nature === "try"); + } + return canBubble; + + //- determine if stackFrame is a try-block or the given type of block + function isTryOrContextBlockType(stackFrame) { + if (_isContextBlockType && _isContextBlockType(stackFrame)) { + return true; + } + return Stack.isTryBlock(stackFrame); + } + } + + function hasUnspentCatch(tryState) { + return (tryState && blkDefFor(tryState).catchIdx && !tryState.hasCaught); + } + function hasUnspentFinally(tryState) { + return (tryState && blkDefFor(tryState).finallyIdx && !tryState.hasFinaled); + } + + function fmtTry(tryState) + { + var tryDef = blkDefFor(tryState); + return ( + (tryDef.name ? "try '" + tryDef.name + "' " : "") + + "@" + (tryState.idx+1) + + ", " + tryState.execPhase + ".." + + " " + $$.tcf.nestingLevel + "n" + ); + } + + function fmtCatching(tryState) + { + if (!tryState) { + return ""; + } + var bbl = ""; + if ($$.tcf.bubbling) { + bbl = "@" + ($$.tcf.bubbling.srcIdx+1) + " "; + } + var tryDef = blkDefFor(tryState); + var catchDcl = testCase.commands[tryDef.catchIdx].target; + return " :: " + bbl + catchDcl; + } + + // ================================================================================ + Selenium.prototype.doWhile = function(condExpr) + { + enterLoop( + function() { // validate + assert(condExpr, " 'while' requires a condition expression."); + assertCompilable("", condExpr, ";", "Invalid condition"); + return null; + } + ,function() { } // initialize + ,function() { return (evalWithVars(condExpr)); } // continue? + ,function() { } // iterate + ); + }; + Selenium.prototype.doEndWhile = function() { + iterateLoop(); + }; + + // ================================================================================ + Selenium.prototype.doFor = function(forSpec) + { + enterLoop( + function(loop) { // validate + assert(forSpec, " 'for' requires: ; ; ."); + assertCompilable("for ( ", forSpec, " );", "Invalid loop parameters"); + var specs = iexpr.splitList(forSpec, ";"); + assert(specs.length === 3, " 'for' requires ; ; ."); + loop.initStmt = specs[0]; + loop.condExpr = specs[1]; + loop.iterStmt = specs[2]; + var localVarNames = parseVarNames(loop.initStmt); + $$.LOG.debug("localVarNames: " + localVarNames.join(',')); + validateNames(localVarNames, "variable"); + return localVarNames; + } + ,function(loop) { evalWithVars(loop.initStmt); } // initialize + ,function(loop) { return (evalWithVars(loop.condExpr)); } // continue? + ,function(loop) { evalWithVars(loop.iterStmt); } // iterate + ); + }; + Selenium.prototype.doEndFor = function() { + iterateLoop(); + }; + + function parseVarNames(initStmt) { + var varNames = []; + if (initStmt) { + var vInits = iexpr.splitList(initStmt, ","); + var i; + for (i = 0; i < vInits.length; i++) { + var vInit = iexpr.splitList(vInits[i], "="); + varNames.push(vInit[0]); + } + } + return varNames; + } + + // ================================================================================ + Selenium.prototype.doForeach = function(varName, valueExpr) + { + enterLoop( + function(loop) { // validate + assert(varName, " 'foreach' requires a variable name."); + assert(valueExpr, " 'foreach' requires comma-separated values."); + assertCompilable("[ ", valueExpr, " ];", "Invalid value list"); + loop.values = evalWithVars("[" + valueExpr + "]"); + if (loop.values.length === 1 && loop.values[0] instanceof Array) { + loop.values = loop.values[0]; // if sole element is an array, than use it + } + return [varName, "_i"]; + } + ,function(loop) { loop.i = 0; storedVars[varName] = loop.values[loop.i]; } // initialize + ,function(loop) { storedVars._i = loop.i; return (loop.i < loop.values.length);} // continue? + ,function(loop) { // iterate + if (++(loop.i) < loop.values.length) { + storedVars[varName] = loop.values[loop.i]; + } + } + ); + }; + Selenium.prototype.doEndForeach = function() { + iterateLoop(); + }; + + // ================================================================================ + Selenium.prototype.doLoadJsonVars = function(filepath, selector) + { + assert(filepath, " Requires a JSON file path or URL."); + var jsonReader = new JSONReader(filepath); + loadVars(jsonReader, "JSON object", filepath, selector); + }; + Selenium.prototype.doLoadXmlVars = function(filepath, selector) + { + assert(filepath, " Requires an XML file path or URL."); + var xmlReader = new XmlReader(filepath); + loadVars(xmlReader, "XML element", filepath, selector); + }; + Selenium.prototype.doLoadVars = function(filepath, selector) + { + $$.LOG.warn("The loadVars command has been deprecated and will be removed in future releases." + + " Please use doLoadXmlVars instead."); + Selenium.prototype.doLoadXmlVars(filepath, selector); + }; + + function loadVars(reader, desc, filepath, selector) + { + if (selector) { + assertCompilable("", selector, ";", "Invalid selector condition"); + } + reader.load(filepath); + reader.next(); // read first varset and set values on storedVars + if (!selector && !reader.EOF()) { + notifyFatalHere(" Multiple " + desc + "s are not valid for this command." + + ' (A specific ' + desc + ' can be selected by specifying: name="value".)'); + } + + var result = evalWithVars(selector); + if (typeof result !== "boolean") { + notifyFatalHere(", " + selector + " is not a boolean expression"); + } + + // read until specified set found + var isEof = reader.EOF(); + while (!isEof && evalWithVars(selector) !== true) { + reader.next(); // read next varset and set values on storedVars + isEof = reader.EOF(); + } + + if (!evalWithVars(selector)) { + notifyFatalHere(desc + " not found for selector expression: " + selector + + "; in input file " + filepath); + } + } + + + // ================================================================================ + Selenium.prototype.doForJson = function(jsonpath) + { + enterLoop( + function(loop) { // validate + assert(jsonpath, " Requires a JSON file path or URL."); + loop.jsonReader = new JSONReader(); + var localVarNames = loop.jsonReader.load(jsonpath); + return localVarNames; + } + ,function() { } // initialize + ,function(loop) { // continue? + var isEof = loop.jsonReader.EOF(); + if (!isEof) { loop.jsonReader.next(); } + return !isEof; + } + ,function() { } + ); + }; + Selenium.prototype.doEndForJson = function() { + iterateLoop(); + }; + + Selenium.prototype.doForXml = function(xmlpath) + { + enterLoop( + function(loop) { // validate + assert(xmlpath, " 'forXml' requires an XML file path or URL."); + loop.xmlReader = new XmlReader(); + var localVarNames = loop.xmlReader.load(xmlpath); + return localVarNames; + } + ,function() { } // initialize + ,function(loop) { // continue? + var isEof = loop.xmlReader.EOF(); + if (!isEof) { loop.xmlReader.next(); } + return !isEof; + } + ,function() { } + ); + }; + Selenium.prototype.doEndForXml = function() { + iterateLoop(); + }; + + + + // -------------------------------------------------------------------------------- + // Note: Selenium variable expansion occurs before command processing, therefore we re-execute + // commands that *may* contain ${} variables. Bottom line, we can't just keep a copy + // of parameters and then iterate back to the first command inside the body of a loop. + + function enterLoop(_validateFunc, _initFunc, _condFunc, _iterFunc) + { + assertRunning(); + var loopState; + if (!activeBlockStack().isHere()) { + // loop begins + loopState = { idx: idxHere() }; + activeBlockStack().push(loopState); + var localVars = _validateFunc(loopState); + loopState.savedVars = getVarState(localVars); + contextManager.enter(); + initVarState(localVars); // because with-scope can reference storedVars only once they exist + _initFunc(loopState); + } + else { + // iteration + loopState = activeBlockStack().top(); + _iterFunc(loopState); + } + + if (!_condFunc(loopState)) { + loopState.isComplete = true; + // jump to bottom of loop for exit + setNextCommand(blkDefHere().endIdx); + } + // else continue into body of loop + } + function iterateLoop() + { + assertRunning(); + assertActiveScope(blkDefHere().beginIdx); + var loopState = activeBlockStack().top(); + var ret; + if (loopState.isComplete) { + if (storedVars._result) { ret = storedVars._result; } + contextManager.exit(); + storedVars._result = ret; + + //restoreVarState(loopState.savedVars); + activeBlockStack().pop(); + // done, fall out of loop + } + else { + // jump back to top of loop + setNextCommand(blkDefHere().beginIdx); + } + } + + // ================================================================================ + Selenium.prototype.doContinue = function(condExpr) { + var loopState = dropToLoop(condExpr); + if (loopState) { + // jump back to top of loop for next iteration, if any + var endCmd = blkDefFor(loopState); + setNextCommand(blkDefAt(endCmd.endIdx).beginIdx); + } + }; + Selenium.prototype.doBreak = function(condExpr) { + var loopState = dropToLoop(condExpr); + if (loopState) { + loopState.isComplete = true; + // jump to bottom of loop for exit + setNextCommand(blkDefFor(loopState).endIdx); + } + }; + + // Unwind the command stack to the inner-most active loop block + // (unless the optional condition evaluates to false) + function dropToLoop(condExpr) + { + assertRunning(); + if (condExpr) { + assertCompilable("", condExpr, ";", "Invalid condition"); + } + if (transitionBubbling(Stack.isLoopBlock)) { + return; + } + if (condExpr && !evalWithVars(condExpr)) { + return; + } + var loopState = activeBlockStack().unwindTo(Stack.isLoopBlock); + return loopState; + } + + + // ================================================================================ + Selenium.prototype.doCall = function(funcName, argSpec) + { + var funcIdx, fName, caseName; + assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? + // throws an error if given gibberish. IE considers the assertion "var;" to be invalid. + // parseArgs, called further below, can handle the empty string just fine. + if (argSpec && argSpec != '') { + assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); + } + if(funcName.match(/[.]/)) { + caseName = String(funcName.split(".")[0]); + fName = String(funcName.split(".")[1]); + } else { + caseName = String(cachedCommandsData.activeCaseTitle); + fName = String(funcName); + } + funcIdx = cachedCommandsData.suites[caseName].symbols[fName]; + assert(funcIdx!==undefined, " Function does not exist: " + funcName); + cachedCommandsData.activeCaseTitle = String(caseName); + + var activeCallFrame = callStack.top(); + if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { + // returning from completed function + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); + callStack.pop() + //restoreVarState(callStack.pop().savedVars); + } + else { + // pass supplied args to the function call through the call stack + var args = parseArgs(argSpec); + // saved vars will be populated by the function call + + callStack.push({ funcIdx: funcIdx, name: fName, args: args, returnIdx: idxHere(), + savedVars: {}, blockStack: new Stack() }); + // jump to function body + setNextCommand(funcIdx); + } + }; + Selenium.prototype.doFunction = function(funcName, paramString) + { + assertRunning(); + var params, savedVars; + var funcDef = blkDefHere(); + var activeCallFrame = callStack.top(); + if (activeCallFrame.funcIdx === idxHere()) { + contextManager.enter(); + params = parseArgs(paramString, "suppress variable expansion"); + // caching the values of all storedVars specified in function signature. + //savedVars = getVarStateFor(params); + //activeCallFrame.savedVars = savedVars; + + // set default values supplied in function definition + setVars(params); + // overwrite local variables and defaults with the supplied values from + // the call + setVars(activeCallFrame.args); + } + else { + // no active call, skip around function body + setNextCommand(funcDef.endIdx); + } + }; + Selenium.prototype.doScript = function(scrName, paramString) + { + $$.LOG.warn("The script command has been deprecated and will be removed in future releases." + + " Please use function instead."); + Selenium.prototype.doFunction(scrName, paramString); + }; + Selenium.prototype.doReturn = function(value) { + returnFromFunction(null, value); + }; + Selenium.prototype.doEndFunction = function(funcName) { + returnFromFunction(funcName); + }; + Selenium.prototype.doEndScript = function(scrName) { + returnFromFunction(scrName); + }; + + function returnFromFunction(funcName, returnVal) + { + assertRunning(); + if (transitionBubbling(Stack.isFunctionBlock)) { + return; + } + var ret; + var endDef = blkDefHere(); + var activeCallFrame = callStack.top(); + if (activeCallFrame.funcIdx !== endDef.funcIdx) { + // no active call, we're just skipping around a function block + } + else { + if (returnVal) { ret = evalWithVars(returnVal); } + contextManager.exit(); + storedVars._result = ret; + activeCallFrame.isReturning = true; + // jump back to call command + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); + setNextCommand(activeCallFrame.returnIdx); + } + } + + + // ================================================================================ + Selenium.prototype.doExitTest = function() { + if (transitionBubbling()) { + return; + } + // intercept command processing and simply stop test execution instead of executing the next command + if(globalContext.onServer === true) { + $$.fn.interceptOnce(htmlTestRunner.currentTest, "resume", $$.handleAsExitTest); + } else { + $$.fn.interceptOnce(editor.selDebugger.runner.currentTest, "resume", $$.handleAsExitTest); + } + }; + + + // ========= storedVars management ========= + + Selenium.prototype.doStoreGlobal = function(value, varName) { + storedVarsGlobal[varName] = value; + }; + + Selenium.prototype.doStoreEvalGlobal = function(value, varName) { + var val = evalWithVars(String(value)); + storedVarsGlobal[varName] = val; + }; + + Selenium.prototype.doStoreGlobalText = function(target, varName) { + var element = this.page().findElement(target); + storedVarsGlobal[varName] = getText(element); + }; + + Selenium.prototype.doStoreGlobalAttribute = function(target, varName) { + storedVarsGlobal[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreLocal = function(value, varName) { + storedVarsLocal[varName] = value; + }; + + Selenium.prototype.doStoreEvalLocal = function(value, varName) { + var val = evalWithVars(String(value)); + storedVarsLocal[varName] = val; + }; + + Selenium.prototype.doStoreLocalText = function(target, varName) { + var element = this.page().findElement(target); + storedVarsLocal[varName] = getText(element); + }; + + Selenium.prototype.doStoreLocalAttribute = function(target, varName) { + storedVarsLocal[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreAt = function(value, varName) { + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + + Selenium.prototype.doStoreEvalAt = function(value, varName) { + var val = evalWithVars(String(value)); + contextManager.storeAtClosestContextWithPropName(varName, val); + }; + + Selenium.prototype.doStoreAtText = function(target, varName) { + var element = this.page().findElement(target); + var value = getText(element); + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + + Selenium.prototype.doStoreAtAttribute = function(target, varName) { + var value = this.page().findAttribute(target); + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + + function evalWithVars(expr) { + var result = null; + try { + // EXTENSION REVIEWERS: Use of eval is consistent with the Selenium extension itself. + // Scripted expressions run in the Selenium window, isolated from any web content. + result = eval("with (storedVars) {" + expr + "}"); + } + catch (e) { + notifyFatalErr(" While evaluating Javascript expression: " + expr, e); + } + return result; + } + /** + * Parses a string of comma separated args that may contain assignments with + * equal signs. + * @param {String} argSpec The string representing arguments. + * @param {Null|Any} suppressEval If this is set to any truthy value then the + * values side of any arguments will not be evaluated with respect to the + * stored variables. + * @returns {Object} Returns an object whose properties are argument names and + * whose property values are the arguments values. If no value was supplied + * then the property will exist but it will be set to undefined. + * @example + * // storedVariables.bat = "XXXXXXX"; + * parseArgs('foo="bar",baz=bat'); + * // returns {foo:"bar", baz:"XXXXXXX"} + * parseArgs('foo="bar",baz=bat', "suppress eval"); + * // returns {foo:"bar", baz:"bat"} + */ + function parseArgs(argSpec, suppressEval) { // comma-sep -> new prop-set + var args = {}; + var parms = iexpr.splitList(argSpec, ","); + var i; + for (i = 0; i < parms.length; i++) { + var keyValue = iexpr.splitList(parms[i], "="); + validateName(keyValue[0], "parameter"); + // boolean values suck, let me put any arbitrary string as the arg + // like "suppress variable expansion" so I can be clear about my intent. + if(suppressEval) { + args[keyValue[0]] = keyValue[1]; + } else { + args[keyValue[0]] = evalWithVars(keyValue[1]); + } + } + return args; + } + function initVarState(names) { // new -> storedVars(names) + if (names) { + var i; + for (i = 0; i < names.length; i++) { + if (!storedVars[names[i]]) { + storedVars[names[i]] = undefined; + } + } + } + } + /** + * Sets the values of existing `args` properties to match `storedVars` + * @param {Object} args A simple value store where properties represent the + * the names of arguments and their values are the default values of those + * properties. If those same properties exist on `storedVars` they will be + * overwritten in the output object. + * @returns {Object} returns a simple object that can be used as `this` in + * `fn.call` and `fn.apply` etc. + */ + function getVarStateFor(args) { // storedVars(prop-set) -> new prop-set + var savedVars = {}; + var varname; + for (varname in args) { + savedVars[varname] = storedVars[varname]; + } + return savedVars; + } + /** + * Gets links to the storedVars specified. + * @param {Array} names An array of strings representing the storedVars + * properties that you want to copy/link to. + * @returns {Object} returns a simple object that can be used as `this` in + * `fn.call` and `fn.apply` etc. + */ + function getVarState(names) { // storedVars(names) -> new prop-set + var savedVars = {}; + if (names) { + var i; + for (i = 0; i < names.length; i++) { + savedVars[names[i]] = storedVars[names[i]]; + } + } + return savedVars; + } + /** + * Overwrites values in storedVars with values supplied. + * @param {Object} args A simple value store where properties represent the + * the names of arguments and their values are the default values of those + * properties. If those same properties exist on `storedVars` they will be + * overwritten. + * @returns {Null} returns nothing. + */ + function setVars(args) { // prop-set -> storedVars + var varname; + for (varname in args) { + storedVars[varname] = args[varname]; + } + } + function restoreVarState(savedVars) { // prop-set --> storedVars + var varname; + for (varname in savedVars) { + if (savedVars[varname] === undefined) { + delete storedVars[varname]; + } + else { + storedVars[varname] = savedVars[varname]; + } + } + } + + // ========= error handling ========= + + function SelblocksError(idx, message) { + this.name = "SelblocksError"; + this.message = (message || ""); + this.idx = idx; + } + SelblocksError.prototype = Error.prototype; + + // TBD: make into throwable Errors + function notifyFatalErr(msg, err) { + $$.LOG.error("Error " + msg); + $$.LOG.logStackTrace(err); + throw err; + } + function notifyFatal(msg) { + var err = new Error(msg); + $$.LOG.error("Error " + msg); + $$.LOG.logStackTrace(err); + throw err; + } + function notifyFatalCmdRef(idx, msg) { notifyFatal(fmtCmdRef(idx) + msg); } + function notifyFatalHere(msg) { notifyFatal(fmtCurCmd() + msg); } + + function assertCmd(idx, cond, msg) { if (!cond) { notifyFatalCmdRef(idx, msg); } } + function assert(cond, msg) { if (!cond) { notifyFatalHere(msg); } } + // TBD: can we at least show result of expressions? + function assertRunning() { + assert(testCase.debugContext.started, " Command is only valid in a running script," + + " i.e., cannot be executed via double-click, or via 'Execute this command'."); + } + function assertActiveScope(expectedIdx) { + var activeIdx = activeBlockStack().top().idx; + assert(activeIdx === expectedIdx, " unexpected command, active command was " + fmtCmdRef(activeIdx)); + } + + function assertCompilable(left, stmt, right, explanation) { + try { + evalWithVars("function selblocksTemp() { " + left + stmt + right + " }"); + } + catch (e) { + throw new SyntaxError(fmtCmdRef(idxHere()) + " " + explanation + " '" + stmt + "': " + e.message); + } + } + + function fmtCurCmd() { + return fmtCmdRef(idxHere()); + } + function fmtCmdRef(idx) { + return ("@" + (idx+1) + ": [" + $$.fmtCmd(testCase.commands[idx]) + "]"); + } + + //================= Utils =============== + + // Elapsed time, optional duration provides expiration + function IntervalTimer(msDuration) { + this.msStart = +new Date(); + this.getElapsed = function() { return (+new Date() - this.msStart); }; + this.hasExpired = function() { return (msDuration && this.getElapsed() > msDuration); }; + this.reset = function() { this.msStart = +new Date(); }; + } + + // produce an iterator object for the given array + function arrayIterator(arrayObject) { + return new function(ary) { + var cur = 0; + this.hasNext = function() { return (cur < ary.length); }; + this.next = function() { if (this.hasNext()) { return ary[cur++]; } }; + }(arrayObject); + }; + + // ==================== Data Files ==================== + // Adapted from the datadriven plugin + // http://web.archive.org/web/20120928080130/http://wiki.openqa.org/display/SEL/datadriven + + function XmlReader() + { + var varsets = null; + var varNames = null; + var curVars = null; + var varsetIdx = 0; + + // load XML file and return the list of var names found in the first element + this.load = function(filepath) + { + var fileReader = new FileReader(); + var fileUrl; + // in order to not break existing tests the IDE will still use urlFor, + // on the server it just breaks things. Data can be anywhere on the net, + // accessible through proper CORS headers. + if(globalContext.onServer === true) { + fileUrl = filepath; + } else { + fileUrl = urlFor(filepath); + } + + var xmlHttpReq = fileReader.getDocumentSynchronous(fileUrl); + $$.LOG.info("Reading from: " + fileUrl); + + var fileObj = xmlHttpReq.responseXML; // XML DOM + varsets = fileObj.getElementsByTagName("vars"); // HTMLCollection + if (varsets === null || varsets.length === 0) { + throw new Error("A element could not be loaded, or was empty."); + } + + curVars = 0; + varNames = attrNamesFor(varsets[0]); + return varNames; + }; + + this.EOF = function() { + return (curVars === null || curVars >= varsets.length); + }; + + this.next = function() + { + if (this.EOF()) { + $$.LOG.error("No more elements to read after element #" + varsetIdx); + return; + } + varsetIdx++; + $$.LOG.debug(varsetIdx + ") " + serializeXml(varsets[curVars])); // log each name & value + + var expected = countAttrs(varsets[0]); + var found = countAttrs(varsets[curVars]); + if (found !== expected) { + throw new Error("Inconsistent at element #" + varsetIdx + + "; expected " + expected + " attributes, but found " + found + "." + + " Each element must have the same set of attributes." + ); + } + setupStoredVars(varsets[curVars]); + curVars++; + }; + + //- retrieve the names of each attribute on the given XML node + function attrNamesFor(node) { + var attrNames = []; + var varAttrs = node.attributes; // NamedNodeMap + var v; + for (v = 0; v < varAttrs.length; v++) { + attrNames.push(varAttrs[v].nodeName); + } + return attrNames; + } + + //- determine how many attributes are present on the given node + function countAttrs(node) { + return node.attributes.length; + } + + //- set selenium variables from given XML attributes + function setupStoredVars(node) { + var varAttrs = node.attributes; // NamedNodeMap + var v; + for (v = 0; v < varAttrs.length; v++) { + var attr = varAttrs[v]; + if (null === varsets[0].getAttribute(attr.nodeName)) { + throw new Error("Inconsistent at element #" + varsetIdx + + "; found attribute " + attr.nodeName + ", which does not appear in the first element." + + " Each element must have the same set of attributes." + ); + } + storedVars[attr.nodeName] = attr.nodeValue; + } + } + + //- format the given XML node for display + function serializeXml(node) { + if (XMLSerializer !== "undefined") { + return (new XMLSerializer()).serializeToString(node) ; + } + if (node.xml) { return node.xml; } + throw "XMLSerializer is not supported or can't serialize " + node; + } + } + + + function JSONReader() + { + var varsets = null; + var varNames = null; + var curVars = null; + var varsetIdx = 0; + + // load JSON file and return the list of var names found in the first object + this.load = function(filepath) + { + var fileReader = new FileReader(); + var fileUrl; + // in order to not break existing tests the IDE will still use urlFor, + // on the server it just breaks things. Data can be anywhere on the net, + // accessible through proper CORS headers. + if(globalContext.onServer === true) { + fileUrl = filepath; + } else { + fileUrl = urlFor(filepath); + } + + var xmlHttpReq = fileReader.getDocumentSynchronous(fileUrl); + $$.LOG.info("Reading from: " + fileUrl); + + var fileObj = xmlHttpReq.responseText; + varsets = eval(fileObj); + if (varsets === null || varsets.length === 0) { + throw new Error("A JSON object could not be loaded, or the file was empty."); + } + + curVars = 0; + varNames = attrNamesFor(varsets[0]); + return varNames; + }; + + this.EOF = function() { + return (curVars === null || curVars >= varsets.length); + }; + + this.next = function() + { + if (this.EOF()) { + $$.LOG.error("No more JSON objects to read after object #" + varsetIdx); + return; + } + varsetIdx++; + $$.LOG.debug(varsetIdx + ") " + JSON.stringify(varsets[curVars])); // log each name & value + + var expected = countAttrs(varsets[0]); + var found = countAttrs(varsets[curVars]); + if (found !== expected) { + throw new Error("Inconsistent JSON object #" + varsetIdx + + "; expected " + expected + " attributes, but found " + found + "." + + " Each JSON object must have the same set of attributes." + ); + } + setupStoredVars(varsets[curVars]); + curVars++; + }; + + //- retrieve the names of each attribute on the given object + function attrNamesFor(obj) { + var attrNames = []; + var attrName; + for (attrName in obj) { + attrNames.push(attrName); + } + return attrNames; + } + + //- determine how many attributes are present on the given obj + function countAttrs(obj) { + var n = 0; + var attrName; + for (attrName in obj) { + n++; + } + return n; + } + + //- set selenium variables from given JSON attributes + function setupStoredVars(obj) { + var attrName; + for (attrName in obj) { + if (null === varsets[0][attrName]) { + throw new Error("Inconsistent JSON at object #" + varsetIdx + + "; found attribute " + attrName + ", which does not appear in the first JSON object." + + " Each JSON object must have the same set of attributes." + ); + } + storedVars[attrName] = obj[attrName]; + } + } + + //- format the given JSON object for display + //function serializeJson(obj) { + // var json = uneval(obj); + // return json.substring(1, json.length-1); + //} + } + + function urlFor(filepath) { + var URL_PFX = "file://"; + var url = filepath; + if (filepath.substring(0, URL_PFX.length).toLowerCase() !== URL_PFX) { + testCasePath = testCase.file.path.replace("\\", "/", "g"); + var i = testCasePath.lastIndexOf("/"); + url = URL_PFX + testCasePath.substr(0, i) + "/" + filepath; + } + return url; + } + + + // ==================== File Reader ==================== + // Adapted from the include4ide plugin + + function FileReader() {} + + FileReader.prototype.prepareUrl = function(url) { + var absUrl; + // htmlSuite mode of SRC? TODO is there a better way to decide whether in SRC mode? + if (window.location.href.indexOf("selenium-server") >= 0) { + $$.LOG.debug("FileReader() is running in SRC mode"); + // there's no need to absolutify the url, the browser will do that for you + // when you make the request. The data may reside anywhere on the site, or + // within the "virtual directory" created by the selenium server proxy. + // I don't want to limit the ability to parse files that actually exist on + // the site, like sitemaps or JSON responses to api calls. + absUrl = url; + } + else { + absUrl = absolutify(url, selenium.browserbot.baseUrl); + } + $$.LOG.debug("FileReader() using URL to get file '" + absUrl + "'"); + return absUrl; + }; + + FileReader.prototype.getDocumentSynchronous = function(url) { + var absUrl = this.prepareUrl(url); + var requester = this.newXMLHttpRequest(); + if (!requester) { + throw new Error("XMLHttp requester object not initialized"); + } + requester.open("GET", absUrl, false); // synchronous (we don't want selenium to go ahead) + try { + requester.send(null); + } + catch(e) { + throw new Error("Error while fetching URL '" + absUrl + "':: " + e); + } + if (requester.status !== 200 && requester.status !== 0) { + throw new Error("Error while fetching " + absUrl + + " server response has status = " + requester.status + ", " + requester.statusText ); + } + return requester; + }; + + FileReader.prototype.newXMLHttpRequest = function() { + var requester = 0; + try { + // for IE/ActiveX + if (window.ActiveXObject) { + try { requester = new ActiveXObject("Msxml2.XMLHTTP"); } + catch(ee) { requester = new ActiveXObject("Microsoft.XMLHTTP"); } + } + // Native XMLHttp + else if (window.XMLHttpRequest) { + requester = new XMLHttpRequest(); + } + } + catch(e) { + throw new Error("Your browser has to support XMLHttpRequest in order to read data files\n" + e); + } + return requester; + }; + +}(selblocks));