From f588037d82554aa6e85e8f509208fe6a4559c39f Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 18 Dec 2014 17:48:03 -0500 Subject: [PATCH 001/116] broke up the try test into individual cases --- sel-blocksTests/_SelBlocks-TestSuite.html | 23 ++- ...- bubble out of nested function calls.html | 181 ++++++++++++++++++ ...t of noop try to catch specific error.html | 131 +++++++++++++ ... - bubble up to catch ALL via finally.html | 136 +++++++++++++ .../try - bubble up to catch ALL.html | 126 ++++++++++++ ...p to catch specific error via finally.html | 141 ++++++++++++++ ...y - bubble up to catch specific error.html | 131 +++++++++++++ sel-blocksTests/try - catch but no error.html | 79 ++++++++ ...y - catch specific error then finally.html | 136 +++++++++++++ .../try - catch specific error.html | 84 ++++++++ .../try - catch throw finally throw.html | 156 +++++++++++++++ ...ommand bubbling continue with finally.html | 119 ++++++++++++ ...d bubbling error replaced by return 2.html | 129 +++++++++++++ ...and bubbling error replaced by return.html | 129 +++++++++++++ ...ry - command bubbling intra try break.html | 119 ++++++++++++ ...- command bubbling intra try continue.html | 119 ++++++++++++ ...and bubbling return replaced by error.html | 156 +++++++++++++++ ... command bubbling, break with finally.html | 119 ++++++++++++ ...ry - exitTest with finally processing.html | 89 +++++++++ .../try - finally with no error.html | 79 ++++++++ sel-blocksTests/try - noop.html | 69 +++++++ .../try - throw catch rethrow.html | 141 ++++++++++++++ .../try - try without matching catch.html | 89 +++++++++ 23 files changed, 2680 insertions(+), 1 deletion(-) create mode 100644 sel-blocksTests/try - bubble out of nested function calls.html create mode 100644 sel-blocksTests/try - bubble up out of noop try to catch specific error.html create mode 100644 sel-blocksTests/try - bubble up to catch ALL via finally.html create mode 100644 sel-blocksTests/try - bubble up to catch ALL.html create mode 100644 sel-blocksTests/try - bubble up to catch specific error via finally.html create mode 100644 sel-blocksTests/try - bubble up to catch specific error.html create mode 100644 sel-blocksTests/try - catch but no error.html create mode 100644 sel-blocksTests/try - catch specific error then finally.html create mode 100644 sel-blocksTests/try - catch specific error.html create mode 100644 sel-blocksTests/try - catch throw finally throw.html create mode 100644 sel-blocksTests/try - command bubbling continue with finally.html create mode 100644 sel-blocksTests/try - command bubbling error replaced by return 2.html create mode 100644 sel-blocksTests/try - command bubbling error replaced by return.html create mode 100644 sel-blocksTests/try - command bubbling intra try break.html create mode 100644 sel-blocksTests/try - command bubbling intra try continue.html create mode 100644 sel-blocksTests/try - command bubbling return replaced by error.html create mode 100644 sel-blocksTests/try - command bubbling, break with finally.html create mode 100644 sel-blocksTests/try - exitTest with finally processing.html create mode 100644 sel-blocksTests/try - finally with no error.html create mode 100644 sel-blocksTests/try - noop.html create mode 100644 sel-blocksTests/try - throw catch rethrow.html create mode 100644 sel-blocksTests/try - try without matching catch.html diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 27faa8c..c860da9 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -12,7 +12,28 @@ eval branching if -try +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 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..f11aa4e --- /dev/null +++ b/sel-blocksTests/try - bubble out of nested function calls.html @@ -0,0 +1,181 @@ + + + + + + +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
functionsubBub
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 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..165cd6a --- /dev/null +++ b/sel-blocksTests/try - command bubbling return replaced by error.html @@ -0,0 +1,156 @@ + + + + + + +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 2~/])"
+ + 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 - 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"
+ + From 479e3444206e1e4ee4bb4d1ce563246e6f36f44a Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 18 Dec 2014 17:58:40 -0500 Subject: [PATCH 002/116] fixed typo in file name, deleted original try test --- sel-blocksTests/_SelBlocks-TestSuite.html | 2 +- ... command bubbling break with finally.html} | 0 sel-blocksTests/try.html | 2323 ----------------- 3 files changed, 1 insertion(+), 2324 deletions(-) rename sel-blocksTests/{try - command bubbling, break with finally.html => try - command bubbling break with finally.html} (100%) delete mode 100644 sel-blocksTests/try.html diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index c860da9..5cdf498 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -25,7 +25,7 @@ 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 break with finally try - command bubbling intra try break try - command bubbling continue with finally try - command bubbling intra try continue diff --git a/sel-blocksTests/try - command bubbling, break with finally.html b/sel-blocksTests/try - command bubbling break with finally.html similarity index 100% rename from sel-blocksTests/try - command bubbling, break with finally.html rename to sel-blocksTests/try - command bubbling break with finally.html diff --git a/sel-blocksTests/try.html b/sel-blocksTests/try.html deleted file mode 100644 index a4e16ee..0000000 --- a/sel-blocksTests/try.html +++ /dev/null @@ -1,2323 +0,0 @@ - - - - - - - -try - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
try
log"-- no-op try --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-noop
emit"trying"
endTryt-noop
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
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~/])"
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~/])"
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'~/])"
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~/])~/])"
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'~/])"
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'~/])"
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'~/])"
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~/])"
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'~/])"
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~/])"
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'~/])"
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
functionsubBub
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~/])"
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~/])"
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~/])"
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~/])"
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~/])"
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~/])"
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~/])"
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 2~/])"
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"
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"
- - From 70aa4afa5c22d0b9434422c41110125e30a9e81c Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 19 Dec 2014 16:27:51 -0500 Subject: [PATCH 003/116] adds conditionally executed code for RC server The new build script will generate user-extensions.js. The new directory "user extension" is for the output user-extension.js and can be used for scripts that may need to be included on the server only. selblocks.js has been altered so that the selblocks object has a new property "onServer" that is false by default. After checking for the existence of "testCase" in the global context, onServer will be set to true if "testCase" does not exist. Using that flag, additional code will be executed if the server environment is detected. --- build/createSelblocksUserExtensions.cmd | 8 + .../chrome/content/extensions/selblocks.js | 59 +- user extension/user-extensions.js | 2227 +++++++++++++++++ 3 files changed, 2292 insertions(+), 2 deletions(-) create mode 100644 build/createSelblocksUserExtensions.cmd create mode 100644 user extension/user-extensions.js diff --git a/build/createSelblocksUserExtensions.cmd b/build/createSelblocksUserExtensions.cmd new file mode 100644 index 0000000..8c06b74 --- /dev/null +++ b/build/createSelblocksUserExtensions.cmd @@ -0,0 +1,8 @@ +@echo off + +SET extensionsDir=%~dp0..\sel-blocks-fx_xpi\chrome\content\extensions +SET userExtensionDir=%~dp0..\user extension + +SET copylist="%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 diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 67e775e..d720cfb 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 @@ -80,9 +79,19 @@ function $X(xpath, contextNode, resultType) { return nodes; } +var globalContext = this; // selbocks name-space (function($$){ - + $$.onServer = globalContext.testCase === undefined ? true : false; + if ($$.onServer === true) { + globalContext.testCase = {}; + HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; + HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { + LOG.info("SelBlocks: wrapper to HtmlRunnerTestLoop.initialize."); + this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); + this.commands = []; + }; + } // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: // Global functions are intentional features provided for use by end user's in their Selenium scripts. @@ -239,6 +248,12 @@ function $X(xpath, contextNode, resultType) { // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) function nextCommand() { + if($$.onServer === true) { + this._advanceToNextRow(); + if (this.currentRow == null) { + return null; + } + } if (!this.started) { this.started = true; this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; @@ -257,6 +272,7 @@ function $X(xpath, contextNode, resultType) { while (this.debugIndex < testCase.commands.length) { var command = testCase.commands[this.debugIndex]; if (command.type === "command") { + this.runTimeStamp = Date.now(); return command; } this.debugIndex++; @@ -267,6 +283,9 @@ function $X(xpath, contextNode, resultType) { assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, " Cannot branch to non-existent command @" + (cmdIdx+1)); branchIdx = cmdIdx; + if($$.onServer === true) { + testCase.htmlTestCase.nextCommandRowIndex = cmdIdx; // w/o branching + } } // Selenium calls reset(): @@ -277,6 +296,42 @@ function $X(xpath, contextNode, resultType) { $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); + if ($$.onServer === true) { + function map_list(list, for_func, if_func) { + var i, + x, + mapped_list = []; + LOG.info("SelBlocks: maplist to get commandrows."); + for (i = 0; i < list.length; ++i) { + x = list[i]; + // AJS: putaquiupariu + if (null == if_func || if_func(i, x)) { + mapped_list.push(for_func(i, x)); + } + } + return mapped_list; + } + if (htmlTestRunner == undefined + || htmlTestRunner == null) { + LOG.info("SelBlocks: Selenium reset pre htmlTestRunner instatiation "); + } else { + LOG.info("SelBlocks: Selenium reset after instatiation of htmlTestRunner.currentTest.htmlTestCase:" + htmlTestRunner.currentTest.htmlTestCase); + //TODO: map commands to real types instead of faking it + htmlTestRunner.currentTest.commands = map_list(htmlTestRunner.currentTest.htmlTestCase.getCommandRows(), function (i, x) { + var b = x.getCommand(); + if (x.hasOwnProperty('trElement')) { + b.type = "command"; + } else { + b.type = "comment"; + } + return b; + }); + // AJS: initializes private testCase (closure) to point to htmlTestRunner.currentTest (public testCase is not available under Core). + testCase = htmlTestRunner.currentTest; + // the debugContext isn't there, but redirecting to the testCase seems to work. + testCase.debugContext = testCase; + } + } try { compileSelBlocks(); } catch (err) { diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js new file mode 100644 index 0000000..e3fffe0 --- /dev/null +++ b/user extension/user-extensions.js @@ -0,0 +1,2227 @@ +// SelBlocks name-space +var selblocks = { name: "SelBlocks" }; + +(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; + }; + +}(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.getInterceptAttrs = function() { + var topFrame = $$.fn.interceptStack[$$.fn.interceptStack.length-1]; + return topFrame.attrs; + }; + + // 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. + // The document is also the starting context, unless a contextNode is provided. + // Results are in terms of the most natural type, unless resultType specified. + evaluateXpath: function(doc, xpath, contextNode, resultType, namespaceResolver, resultObj) + { + $$.xp.logXpathEval(doc, xpath, contextNode); + var isResultObjProvided = (resultObj != null); + try { + var result = doc.evaluate( + xpath + , contextNode || doc + , namespaceResolver + , resultType || XPathResult.ANY_TYPE + , 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. + * It alters command processing such that the script simply halts rather executing 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); // causes command to be marked in red + this.testComplete(); + } + $$.LOG.info("TEST HALTED"); + }; + +}(selblocks)); +// selbocks name-space +(function($$){ + /* This function replaces native Selenium command handling while inside a try block. + */ + $$.handleAsTryBlock = function() + { + try { + selenium.browserbot.runScheduledPollers(); + this._executeCurrentCommand(); + this.continueTestWhenConditionIsTrue(); + } catch (e) { + var isHandled = this._handleCommandError(e); // causes command to be marked in red + var handlerAttrs = $$.fn.getInterceptAttrs(); + var isManaged = handlerAttrs.handleError(e); + if (isManaged) { + this.continueTest(); + } else { + this.testComplete(); + } + } + }; + +}(selblocks)); +/* + * SelBlocks 2.0.1 + * + * 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; +} + +var globalContext = this; +// selbocks name-space +(function($$){ + $$.onServer = globalContext.testCase === undefined ? true : false; + if ($$.onServer === true) { + globalContext.testCase = {}; + HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; + HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { + LOG.info("SelBlocks: wrapper to HtmlRunnerTestLoop.initialize."); + this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); + this.commands = []; + }; + } + // =============== 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 + + // the idx of the currently executing command + function idxHere() { + return testCase.debugContext.debugIndex; + } + + // 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) { + return blockDefs[idx]; + } + // 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($$.onServer === true) { + this._advanceToNextRow(); + if (this.currentRow == null) { + return null; + } + } + if (!this.started) { + this.started = true; + this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; + } + else { + if (branchIdx !== null) { + $$.LOG.info("branch => " + fmtCmdRef(branchIdx)); + this.debugIndex = branchIdx; + branchIdx = null; + } + else { + this.debugIndex++; + } + } + // skip over comments + while (this.debugIndex < testCase.commands.length) { + var command = testCase.commands[this.debugIndex]; + if (command.type === "command") { + this.runTimeStamp = Date.now(); + return command; + } + this.debugIndex++; + } + return null; + } + function setNextCommand(cmdIdx) { + assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, + " Cannot branch to non-existent command @" + (cmdIdx+1)); + branchIdx = cmdIdx; + if($$.onServer === true) { + testCase.htmlTestCase.nextCommandRowIndex = cmdIdx; // w/o branching + } + } + + // 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()"); + if ($$.onServer === true) { + function map_list(list, for_func, if_func) { + var i, + x, + mapped_list = []; + LOG.info("SelBlocks: maplist to get commandrows."); + for (i = 0; i < list.length; ++i) { + x = list[i]; + // AJS: putaquiupariu + if (null == if_func || if_func(i, x)) { + mapped_list.push(for_func(i, x)); + } + } + return mapped_list; + } + if (htmlTestRunner == undefined + || htmlTestRunner == null) { + LOG.info("SelBlocks: Selenium reset pre htmlTestRunner instatiation "); + } else { + LOG.info("SelBlocks: Selenium reset after instatiation of htmlTestRunner.currentTest.htmlTestCase:" + htmlTestRunner.currentTest.htmlTestCase); + //TODO: map commands to real types instead of faking it + htmlTestRunner.currentTest.commands = map_list(htmlTestRunner.currentTest.htmlTestCase.getCommandRows(), function (i, x) { + var b = x.getCommand(); + if (x.hasOwnProperty('trElement')) { + b.type = "command"; + } else { + b.type = "comment"; + } + return b; + }); + // AJS: initializes private testCase (closure) to point to htmlTestRunner.currentTest (public testCase is not available under Core). + testCase = htmlTestRunner.currentTest; + // the debugContext isn't there, but redirecting to the testCase seems to work. + testCase.debugContext = testCase; + } + } + try { + 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 }; + + // 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); + }); + + // get the blockStack for the currently active callStack + function activeBlockStack() { + return callStack.top().blockStack; + } + + // ================================================================================ + // Assemble block relationships and symbol locations + function compileSelBlocks() + { + 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("; ")); + } + //- 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)); + } + } + + // -------------------------------------------------------------------------------- + + // prevent 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 + $$.fn.interceptPush(editor.selDebugger.runner.IDETestLoop.prototype, "resume", + $$.handleAsTryBlock, { handleError: 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 error is being managed + function handleCommandError(err) + { + var tryState = bubbleToTryBlock(Stack.isTryBlock); + var tryDef = blkDefFor(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); + while (!tryState && $$.tcf.nestingLevel > -1 && callStack.length > 1) { + var callFrame = callStack.pop(); + $$.LOG.info("function '" + callFrame.name + "' aborting due to error"); + 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 (blkDefFor(tryState).catchIdx && !tryState.hasCaught); + } + function hasUnspentFinally(tryState) { + return (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); + 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(); + if (loopState.isComplete) { + 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) + { + assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? + if (argSpec) { + assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); + } + var funcIdx = symbols[funcName]; + assert(funcIdx!==undefined, " Function does not exist: " + funcName + "."); + + var activeCallFrame = callStack.top(); + if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { + // returning from completed function + restoreVarState(callStack.pop().savedVars); + } + else { + // save existing variable state and set args as local variables + var args = parseArgs(argSpec); + var savedVars = getVarStateFor(args); + setVars(args); + + callStack.push({ funcIdx: funcIdx, name: funcName, args: args, returnIdx: idxHere(), + savedVars: savedVars, blockStack: new Stack() }); + // jump to function body + setNextCommand(funcIdx); + } + }; + Selenium.prototype.doFunction = function(funcName) + { + assertRunning(); + + var funcDef = blkDefHere(); + var activeCallFrame = callStack.top(); + if (activeCallFrame.funcIdx === idxHere()) { + // get parameter values + setVars(activeCallFrame.args); + } + else { + // no active call, skip around function body + setNextCommand(funcDef.endIdx); + } + }; + Selenium.prototype.doScript = function(scrName) + { + $$.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.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 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); } + activeCallFrame.isReturning = true; + // jump back to call command + setNextCommand(activeCallFrame.returnIdx); + } + } + + + // ================================================================================ + Selenium.prototype.doExitTest = function() { + if (transitionBubbling()) { + return; + } + // intercept command processing and simply stop test execution instead of executing the next command + $$.fn.interceptOnce(editor.selDebugger.runner.IDETestLoop.prototype, "resume", $$.handleAsExitTest); + }; + + + // ========= storedVars management ========= + + 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; + } + + function parseArgs(argSpec) { // 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]); + } + 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]] = null; + } + } + } + } + function getVarStateFor(args) { // storedVars(prop-set) -> new prop-set + var savedVars = {}; + var varname; + for (varname in args) { + savedVars[varname] = storedVars[varname]; + } + return savedVars; + } + 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; + } + 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) + ": " + fmtCommand(testCase.commands[idx])); + } + function fmtCommand(cmd) { + var c = cmd.command; + if (cmd.target) { c += "|" + cmd.target; } + if (cmd.value) { c += "|" + cmd.value; } + return '[' + c + ']'; + } + + //================= 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 = 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 = 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 + ") " + serializeJson(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"); + absUrl = absolutify(url, htmlTestRunner.controlPanel.getTestSuiteName()); + } 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)); From 317ae2503ce588d9aa83abdd1906a72ceeb55f2e Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 19 Dec 2014 18:05:47 -0500 Subject: [PATCH 004/116] sets whether on server or not by config.js Detecting whether this is running on the server or not is silly. I just include a setting when creating the user-extension. If the setting is set, then extra code for the server gets executed. If the setting is undefined, then the server code is not executed. The extension passes the test suite and the server extension doesn't crash on the server. Now I'll figure out SelBench and we'll be able to run the full test suite on the server. --- build/createSelblocksUserExtensions.cmd | 2 +- .../chrome/content/extensions/selblocks.js | 9 ++++----- user extension/scripts/config.js | 1 + user extension/user-extensions.js | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 user extension/scripts/config.js diff --git a/build/createSelblocksUserExtensions.cmd b/build/createSelblocksUserExtensions.cmd index 8c06b74..2645327 100644 --- a/build/createSelblocksUserExtensions.cmd +++ b/build/createSelblocksUserExtensions.cmd @@ -3,6 +3,6 @@ SET extensionsDir=%~dp0..\sel-blocks-fx_xpi\chrome\content\extensions SET userExtensionDir=%~dp0..\user extension -SET copylist="%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" +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 diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index d720cfb..fda55ad 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -82,8 +82,7 @@ function $X(xpath, contextNode, resultType) { var globalContext = this; // selbocks name-space (function($$){ - $$.onServer = globalContext.testCase === undefined ? true : false; - if ($$.onServer === true) { + if(globalContext.onServer === true) { globalContext.testCase = {}; HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { @@ -248,7 +247,7 @@ var globalContext = this; // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) function nextCommand() { - if($$.onServer === true) { + if(globalContext.onServer === true) { this._advanceToNextRow(); if (this.currentRow == null) { return null; @@ -283,7 +282,7 @@ var globalContext = this; assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, " Cannot branch to non-existent command @" + (cmdIdx+1)); branchIdx = cmdIdx; - if($$.onServer === true) { + if(globalContext.onServer === true) { testCase.htmlTestCase.nextCommandRowIndex = cmdIdx; // w/o branching } } @@ -296,7 +295,7 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if ($$.onServer === true) { + if (globalContext.onServer === true) { function map_list(list, for_func, if_func) { var i, x, diff --git a/user extension/scripts/config.js b/user extension/scripts/config.js new file mode 100644 index 0000000..fc983f3 --- /dev/null +++ b/user extension/scripts/config.js @@ -0,0 +1 @@ +this.onServer = true; diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index e3fffe0..e4fe21c 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -1,3 +1,4 @@ +this.onServer = true; // SelBlocks name-space var selblocks = { name: "SelBlocks" }; @@ -502,8 +503,7 @@ function $X(xpath, contextNode, resultType) { var globalContext = this; // selbocks name-space (function($$){ - $$.onServer = globalContext.testCase === undefined ? true : false; - if ($$.onServer === true) { + if(globalContext.onServer === true) { globalContext.testCase = {}; HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { @@ -668,7 +668,7 @@ var globalContext = this; // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) function nextCommand() { - if($$.onServer === true) { + if(globalContext.onServer === true) { this._advanceToNextRow(); if (this.currentRow == null) { return null; @@ -703,7 +703,7 @@ var globalContext = this; assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, " Cannot branch to non-existent command @" + (cmdIdx+1)); branchIdx = cmdIdx; - if($$.onServer === true) { + if(globalContext.onServer === true) { testCase.htmlTestCase.nextCommandRowIndex = cmdIdx; // w/o branching } } @@ -716,7 +716,7 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if ($$.onServer === true) { + if (globalContext.onServer === true) { function map_list(list, for_func, if_func) { var i, x, From 3824aa9e56e57aaefbf591c8d2f4c1af674da39e Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 19 Dec 2014 20:44:38 -0500 Subject: [PATCH 005/116] adds script for running tests on server SelBench user extension still needs work, but once it's right this should be a snap to test. This will grab the user-extensions.js file in C:\projects\selenium\selbench\SelBench\user extension Assuming you have this script at C:\projects\selenium\selblocks\SelBlocks\testUserExtension then it will concatenate the selbench script with the user extension for selblocks and the tests will be run. --- testUserExtension/.gitignore | 3 ++ testUserExtension/runTestsOnServer.cmd | 61 ++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 testUserExtension/.gitignore create mode 100644 testUserExtension/runTestsOnServer.cmd diff --git a/testUserExtension/.gitignore b/testUserExtension/.gitignore new file mode 100644 index 0000000..80bf25c --- /dev/null +++ b/testUserExtension/.gitignore @@ -0,0 +1,3 @@ +*Log* +results* +user-extensions.js \ No newline at end of file diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd new file mode 100644 index 0000000..d137b32 --- /dev/null +++ b/testUserExtension/runTestsOnServer.cmd @@ -0,0 +1,61 @@ +@ echo off + +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 + +SET resultsLog=%~dp0\results +SET serverLog=%~dp0\Selenium Server Log.txt +SET testSuite=%~dp0..\sel-blocksTests\_SelBlocks-TestSuite.html +SET userExtensions=%~dp0\user-extensions.js + +rem creates the user extension with selbench and selblocks +SET selblocksUserExtension=%~dp0..\user extension\user-extensions.js +SET selbenchUserExtension=%~dp0..\..\..\selbench\SelBench\user extension\user-extensions.js +COPY "%selbenchUserExtension%"+"%selblocksUserExtension%" /B "%userExtensions%" /B + +REM C:\projects\selenium\server\ +REM selenium-server-standalone*.jar, chromedriver.exe, and IEDriverServer.exe +SET seleniumLocation=%~dp0..\..\..\server\ + +SET baseURL=http://localhost:4444 + +rem deletes the existing logs and results +FOR %%I IN ("%serverLog%*") DO DEL /Q "%%I" +FOR %%I IN (results-*.html) DO DEL /Q "%%I" + +rem Sets the seleniumServerJar variable to the path of the one with the highest +rem version in the directory pointed at by seleniumLocation +FOR %%I IN (%seleniumLocation%\selenium-server-standalone*.jar) DO SET seleniumServerJar=%%~dpnxI + +REM runs test suite specified by testSuite, in firefox +SET browser=firefox +start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" +rem uncomment the following lines once selbench works on the server with firefox. +rem we'll deal with browser inconsistencies after we get things up and running. + +rem "%resultsLog%-%browser%.html" +rem SET browser=piiexplore +rem start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" +rem "%resultsLog%-%browser%.html" +rem SET browser=googlechrome +rem start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" +rem "%resultsLog%-%browser%.html" From 4caa6c423b49ea72703b9a04bd3e303cc81ed73a Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 19 Dec 2014 22:50:25 -0500 Subject: [PATCH 006/116] fixes recursion issue both selbench and selblocks applied the same patches and ended up creating a loop that never ended. Now they flag when they've applied patches and check the flags before applying them. --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 6 ++++-- user extension/user-extensions.js | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index fda55ad..43b92ce 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -82,7 +82,7 @@ function $X(xpath, contextNode, resultType) { var globalContext = this; // selbocks name-space (function($$){ - if(globalContext.onServer === true) { + if(globalContext.onServer === true && globalContext.scriptServerPatchApplied !== true) { globalContext.testCase = {}; HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { @@ -90,6 +90,7 @@ var globalContext = this; this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); this.commands = []; }; + globalContext.scriptServerPatchApplied = true; } // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: @@ -295,7 +296,8 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if (globalContext.onServer === true) { + if (globalContext.onServer === true && globalContext.scriptInterceptsSeleniumReset !== true) { + globalContext.scriptInterceptsSeleniumReset = true; function map_list(list, for_func, if_func) { var i, x, diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index e4fe21c..9242240 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -503,7 +503,7 @@ function $X(xpath, contextNode, resultType) { var globalContext = this; // selbocks name-space (function($$){ - if(globalContext.onServer === true) { + if(globalContext.onServer === true && globalContext.scriptServerPatchApplied !== true) { globalContext.testCase = {}; HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { @@ -511,6 +511,7 @@ var globalContext = this; this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); this.commands = []; }; + globalContext.scriptServerPatchApplied = true; } // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: @@ -716,7 +717,8 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if (globalContext.onServer === true) { + if (globalContext.onServer === true && globalContext.scriptInterceptsSeleniumReset !== true) { + globalContext.scriptInterceptsSeleniumReset = true; function map_list(list, for_func, if_func) { var i, x, From 4eb0a1cb3e554ca458449b172f55525e43696179 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 19 Dec 2014 23:02:00 -0500 Subject: [PATCH 007/116] renamed test The pound sign works in the IDE but screws up the server when it tries to fetch the test. --- sel-blocksTests/_SelBlocks-TestSuite.html | 2 +- .../{issue#2-function.html => issue-2-function.html} | 0 testUserExtension/runTestsOnServer.cmd | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) rename sel-blocksTests/{issue#2-function.html => issue-2-function.html} (100%) diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 27faa8c..62bf455 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -23,7 +23,7 @@ nested-loops function function-recursive -issue#2-function +issue-2-function exitTest 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/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index d137b32..1a1b134 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -49,10 +49,11 @@ FOR %%I IN (%seleniumLocation%\selenium-server-standalone*.jar) DO SET seleniumS REM runs test suite specified by testSuite, in firefox SET browser=firefox start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" +"%resultsLog%-%browser%.html" + rem uncomment the following lines once selbench works on the server with firefox. rem we'll deal with browser inconsistencies after we get things up and running. -rem "%resultsLog%-%browser%.html" rem SET browser=piiexplore rem start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" rem "%resultsLog%-%browser%.html" From c24a37c0a8723a052c2d3c823758c8f60d5a1845 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 19 Dec 2014 23:55:17 -0500 Subject: [PATCH 008/116] conditional execution "editor" missing on server --- .../chrome/content/extensions/selblocks.js | 18 +++++++++++++++--- user extension/user-extensions.js | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 43b92ce..7e96b00 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -775,8 +775,14 @@ var globalContext = this; if ($$.tcf.nestingLevel === 0) { // enable special command handling - $$.fn.interceptPush(editor.selDebugger.runner.IDETestLoop.prototype, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); + if(globalContext.onServer === true) { + $$.fn.interceptPush(HtmlRunnerTestLoop.prototype, "resume", + $$.handleAsTryBlock, { handleError: handleCommandError }); + } else { + $$.fn.interceptPush(editor.selDebugger.runner.IDETestLoop.prototype, "resume", + $$.handleAsTryBlock, { handleError: handleCommandError }); + } + } $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); // continue into try-block @@ -1395,7 +1401,13 @@ var globalContext = this; return; } // intercept command processing and simply stop test execution instead of executing the next command - $$.fn.interceptOnce(editor.selDebugger.runner.IDETestLoop.prototype, "resume", $$.handleAsExitTest); + if(globalContext.onServer === true) { + $$.fn.interceptOnce(HtmlRunnerTestLoop.prototype, "resume", + $$.handleAsExitTest); + } else { + $$.fn.interceptOnce(editor.selDebugger.runner.IDETestLoop.prototype, "resume", + $$.handleAsExitTest); + } }; diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 9242240..6d2be47 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -1196,8 +1196,14 @@ var globalContext = this; if ($$.tcf.nestingLevel === 0) { // enable special command handling - $$.fn.interceptPush(editor.selDebugger.runner.IDETestLoop.prototype, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); + if(globalContext.onServer === true) { + $$.fn.interceptPush(HtmlRunnerTestLoop.prototype, "resume", + $$.handleAsTryBlock, { handleError: handleCommandError }); + } else { + $$.fn.interceptPush(editor.selDebugger.runner.IDETestLoop.prototype, "resume", + $$.handleAsTryBlock, { handleError: handleCommandError }); + } + } $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); // continue into try-block @@ -1816,7 +1822,13 @@ var globalContext = this; return; } // intercept command processing and simply stop test execution instead of executing the next command - $$.fn.interceptOnce(editor.selDebugger.runner.IDETestLoop.prototype, "resume", $$.handleAsExitTest); + if(globalContext.onServer === true) { + $$.fn.interceptOnce(HtmlRunnerTestLoop.prototype, "resume", + $$.handleAsExitTest); + } else { + $$.fn.interceptOnce(editor.selDebugger.runner.IDETestLoop.prototype, "resume", + $$.handleAsExitTest); + } }; From 7b632d1ec10f5157a91b328ba2f316b7e8c0e428 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 20 Dec 2014 03:37:45 -0500 Subject: [PATCH 009/116] resolves conflicts --- .../chrome/content/extensions/selblocks.js | 41 +++++++------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index ec0d727..15cf5c0 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -775,20 +775,14 @@ var globalContext = this; tryState.execPhase = "trying"; if ($$.tcf.nestingLevel === 0) { - // enable special command handling -<<<<<<< HEAD - if(globalContext.onServer === true) { - $$.fn.interceptPush(HtmlRunnerTestLoop.prototype, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); - } else { - $$.fn.interceptPush(editor.selDebugger.runner.IDETestLoop.prototype, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); - } - -======= - $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", - $$.handleAsTryBlock, { manageError: handleCommandError }); ->>>>>>> origin/master + // enable special command handling + if(globalContext.onServer === true) { + $$.fn.interceptPush(htmlTestRunner.currentTest, "resume", + $$.handleAsTryBlock, { handleError: handleCommandError }); + } else { + $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", + $$.handleAsTryBlock, { manageError: handleCommandError }); + } } $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); // continue into try-block @@ -1408,18 +1402,13 @@ var globalContext = this; if (transitionBubbling()) { return; } - // intercept command processing and simply stop test execution instead of executing the next command -<<<<<<< HEAD - if(globalContext.onServer === true) { - $$.fn.interceptOnce(HtmlRunnerTestLoop.prototype, "resume", - $$.handleAsExitTest); - } else { - $$.fn.interceptOnce(editor.selDebugger.runner.IDETestLoop.prototype, "resume", - $$.handleAsExitTest); - } -======= - $$.fn.interceptOnce(editor.selDebugger.runner.currentTest, "resume", $$.handleAsExitTest); ->>>>>>> origin/master + // 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); + } }; From 8c14aaee210d0b2cdd6648482ecf991c060bb211 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 20 Dec 2014 03:42:55 -0500 Subject: [PATCH 010/116] rebuilt with latest upstream master This doesn't pass testing yet. The tests run but almost all of them fail. --- user extension/user-extensions.js | 138 ++++++++++++++++++------------ 1 file changed, 84 insertions(+), 54 deletions(-) diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 6d2be47..0a3291e 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -15,6 +15,13 @@ var selblocks = { name: "SelBlocks" }; 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($$){ @@ -132,9 +139,9 @@ var selblocks = { name: "SelBlocks" }; // $$.LOG.warn("interceptPop " + (frame.attrs ? frame.attrs : "")); frame.targetObj[frame.targetFnName] = frame.savedFn; }; - $$.fn.getInterceptAttrs = function() { - var topFrame = $$.fn.interceptStack[$$.fn.interceptStack.length-1]; - return topFrame.attrs; + + $$.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 @@ -380,7 +387,8 @@ var selblocks = { name: "SelBlocks" }; // selbocks name-space (function($$){ /* This function replaces native Selenium command handling for the exitScript command. - * It alters command processing such that the script simply halts rather executing the next 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() { @@ -389,7 +397,7 @@ var selblocks = { name: "SelBlocks" }; this.testComplete(); } catch (e) { // seems highly unlikely that there would be an error in this very simple case - this._handleCommandError(e); // causes command to be marked in red + this._handleCommandError(e); // marks command as failed (red), and overall test as failed this.testComplete(); } $$.LOG.info("TEST HALTED"); @@ -399,28 +407,52 @@ var selblocks = { name: "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(); - this.continueTestWhenConditionIsTrue(); + 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) { - var isHandled = this._handleCommandError(e); // causes command to be marked in red - var handlerAttrs = $$.fn.getInterceptAttrs(); - var isManaged = handlerAttrs.handleError(e); - if (isManaged) { + if (isManaged(e)) { + // a caught error has activated catch/finally bubbling this.continueTest(); - } else { - this.testComplete(); + } + 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(); + if (e.constructor.name == "AssertResult") { + e = new Error(e.failureMessage); + } + return (interceptFrame && interceptFrame.attrs.manageError(e)); + } }; }(selblocks)); /* - * SelBlocks 2.0.1 + * SelBlocks 2.0.2 * * Provides commands for Javascript-like looping and callable functions, * with scoped variables, and JSON/XML driven parameterization. @@ -756,13 +788,14 @@ var globalContext = this; } try { compileSelBlocks(); - } catch (err) { + } + catch (err) { notifyFatalErr("In " + err.fileName + " @" + err.lineNumber + ": " + err); } callStack = new Stack(); callStack.push({ blockStack: new Stack() }); // top-level execution state - $$.tcf = { nestingLevel: -1 }; + $$.tcf = { nestingLevel: -1 }; // try/catch/finally nesting // customize flow control logic // TBD: this should be a tail intercept rather than brute force replace @@ -1196,14 +1229,13 @@ var globalContext = this; if ($$.tcf.nestingLevel === 0) { // enable special command handling - if(globalContext.onServer === true) { - $$.fn.interceptPush(HtmlRunnerTestLoop.prototype, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); - } else { - $$.fn.interceptPush(editor.selDebugger.runner.IDETestLoop.prototype, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); - } - + if(globalContext.onServer === true) { + $$.fn.interceptPush(htmlTestRunner.currentTest, "resume", + $$.handleAsTryBlock, { handleError: handleCommandError }); + } else { + $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", + $$.handleAsTryBlock, { manageError: handleCommandError }); + } } $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); // continue into try-block @@ -1263,22 +1295,24 @@ var globalContext = this; // -------------------------------------------------------------------------------- // alter the behavior of Selenium error handling - // returns true if error is being managed + // returns true if catch/finally bubbling is active function handleCommandError(err) { var tryState = bubbleToTryBlock(Stack.isTryBlock); var tryDef = blkDefFor(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; + 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 @@ -1441,10 +1475,10 @@ var globalContext = this; } function hasUnspentCatch(tryState) { - return (blkDefFor(tryState).catchIdx && !tryState.hasCaught); + return (tryState && blkDefFor(tryState).catchIdx && !tryState.hasCaught); } function hasUnspentFinally(tryState) { - return (blkDefFor(tryState).finallyIdx && !tryState.hasFinaled); + return (tryState && blkDefFor(tryState).finallyIdx && !tryState.hasFinaled); } function fmtTry(tryState) @@ -1822,13 +1856,12 @@ var globalContext = this; return; } // intercept command processing and simply stop test execution instead of executing the next command - if(globalContext.onServer === true) { - $$.fn.interceptOnce(HtmlRunnerTestLoop.prototype, "resume", - $$.handleAsExitTest); - } else { - $$.fn.interceptOnce(editor.selDebugger.runner.IDETestLoop.prototype, "resume", - $$.handleAsExitTest); - } + if(globalContext.onServer === true) { + $$.fn.interceptOnce(htmlTestRunner.currentTest, "resume", + $$.handleAsExitTest); + } else { + $$.fn.interceptOnce(editor.selDebugger.runner.currentTest, "resume", $$.handleAsExitTest); + } }; @@ -1840,7 +1873,8 @@ var globalContext = this; // 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) { + } + catch (e) { notifyFatalErr(" While evaluating Javascript expression: " + expr, e); } return result; @@ -1952,13 +1986,7 @@ var globalContext = this; return fmtCmdRef(idxHere()); } function fmtCmdRef(idx) { - return ("@" + (idx+1) + ": " + fmtCommand(testCase.commands[idx])); - } - function fmtCommand(cmd) { - var c = cmd.command; - if (cmd.target) { c += "|" + cmd.target; } - if (cmd.value) { c += "|" + cmd.value; } - return '[' + c + ']'; + return ("@" + (idx+1) + ": [" + $$.fmtCmd(testCase.commands[idx]) + "]"); } //================= Utils =============== @@ -2193,7 +2221,8 @@ var globalContext = this; if (window.location.href.indexOf("selenium-server") >= 0) { $$.LOG.debug("FileReader() is running in SRC mode"); absUrl = absolutify(url, htmlTestRunner.controlPanel.getTestSuiteName()); - } else { + } + else { absUrl = absolutify(url, selenium.browserbot.baseUrl); } $$.LOG.debug("FileReader() using URL to get file '" + absUrl + "'"); @@ -2209,7 +2238,8 @@ var globalContext = this; requester.open("GET", absUrl, false); // synchronous (we don't want selenium to go ahead) try { requester.send(null); - } catch(e) { + } + catch(e) { throw new Error("Error while fetching URL '" + absUrl + "':: " + e); } if (requester.status !== 200 && requester.status !== 0) { From ff3538d4dd7fa0a7a1a67222c9ecefe188628110 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 20 Dec 2014 14:19:16 -0500 Subject: [PATCH 011/116] changing guard this code has to run once, and only once, every time the reset method is intercepted. It has to run after the original reset method has executed, but before any tests are actually run. I'll have to move it out into its own file and intercept the call to reset before any other extensions do. --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 4 ++-- user extension/user-extensions.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 15cf5c0..ec00a8c 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -296,8 +296,8 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if (globalContext.onServer === true && globalContext.scriptInterceptsSeleniumReset !== true) { - globalContext.scriptInterceptsSeleniumReset = true; + if (globalContext.onServer === true) { + //globalContext.scriptInterceptsSeleniumReset = true; function map_list(list, for_func, if_func) { var i, x, diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 0a3291e..2c69093 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -749,8 +749,8 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if (globalContext.onServer === true && globalContext.scriptInterceptsSeleniumReset !== true) { - globalContext.scriptInterceptsSeleniumReset = true; + if (globalContext.onServer === true) { + //globalContext.scriptInterceptsSeleniumReset = true; function map_list(list, for_func, if_func) { var i, x, From 6cd1777003f3c9ba6748f278748d3633067c68bf Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 20 Dec 2014 19:09:59 -0500 Subject: [PATCH 012/116] moved server augmentation code to config.js This moves the server augmentation code out of the FF extension. This appears to be working, I'm missing some mappings between obejcts and methods on the server and IDE though. This passes testing in the IDE but fails gloriously on the server. The "while" test makes the screen twitch because the incrementor never increments. I'm sure it's something simple once I look... --- .../chrome/content/extensions/name-space.js | 5 + .../chrome/content/extensions/selblocks.js | 51 +------ user extension/scripts/config.js | 82 ++++++++++- user extension/user-extensions.js | 138 +++++++++++------- 4 files changed, 174 insertions(+), 102 deletions(-) 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 ec00a8c..b8a99f1 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -79,19 +79,8 @@ function $X(xpath, contextNode, resultType) { return nodes; } -var globalContext = this; // selbocks name-space (function($$){ - if(globalContext.onServer === true && globalContext.scriptServerPatchApplied !== true) { - globalContext.testCase = {}; - HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; - HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { - LOG.info("SelBlocks: wrapper to HtmlRunnerTestLoop.initialize."); - this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); - this.commands = []; - }; - globalContext.scriptServerPatchApplied = true; - } // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: // Global functions are intentional features provided for use by end user's in their Selenium scripts. @@ -296,43 +285,6 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if (globalContext.onServer === true) { - //globalContext.scriptInterceptsSeleniumReset = true; - function map_list(list, for_func, if_func) { - var i, - x, - mapped_list = []; - LOG.info("SelBlocks: maplist to get commandrows."); - for (i = 0; i < list.length; ++i) { - x = list[i]; - // AJS: putaquiupariu - if (null == if_func || if_func(i, x)) { - mapped_list.push(for_func(i, x)); - } - } - return mapped_list; - } - if (htmlTestRunner == undefined - || htmlTestRunner == null) { - LOG.info("SelBlocks: Selenium reset pre htmlTestRunner instatiation "); - } else { - LOG.info("SelBlocks: Selenium reset after instatiation of htmlTestRunner.currentTest.htmlTestCase:" + htmlTestRunner.currentTest.htmlTestCase); - //TODO: map commands to real types instead of faking it - htmlTestRunner.currentTest.commands = map_list(htmlTestRunner.currentTest.htmlTestCase.getCommandRows(), function (i, x) { - var b = x.getCommand(); - if (x.hasOwnProperty('trElement')) { - b.type = "command"; - } else { - b.type = "comment"; - } - return b; - }); - // AJS: initializes private testCase (closure) to point to htmlTestRunner.currentTest (public testCase is not available under Core). - testCase = htmlTestRunner.currentTest; - // the debugContext isn't there, but redirecting to the testCase seems to work. - testCase.debugContext = testCase; - } - } try { compileSelBlocks(); } @@ -1404,8 +1356,7 @@ var globalContext = this; } // intercept command processing and simply stop test execution instead of executing the next command if(globalContext.onServer === true) { - $$.fn.interceptOnce(htmlTestRunner.currentTest, "resume", - $$.handleAsExitTest); + $$.fn.interceptOnce(htmlTestRunner.currentTest, "resume", $$.handleAsExitTest); } else { $$.fn.interceptOnce(editor.selDebugger.runner.currentTest, "resume", $$.handleAsExitTest); } diff --git a/user extension/scripts/config.js b/user extension/scripts/config.js index fc983f3..41774fe 100644 --- a/user extension/scripts/config.js +++ b/user extension/scripts/config.js @@ -1 +1,81 @@ -this.onServer = true; +/*jslint +indent:2, +maxerr:500, +plusplus:true + */ +/*globals +selblocks, +HtmlRunnerTestLoop, +Selenium, +htmlTestRunner + */ +var globalContext = this; +globalContext.onServer = globalContext.onServer || true; +globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; + +function seleniumResetInterceptor() { + "use strict"; + 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; + } + }; +} + +function patchServerEnvironment() { + "use strict"; + + 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(); +} diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 2c69093..192d7e9 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -1,7 +1,92 @@ -this.onServer = true; +/*jslint +indent:2, +maxerr:500, +plusplus:true + */ +/*globals +selblocks, +HtmlRunnerTestLoop, +Selenium, +htmlTestRunner + */ +var globalContext = this; +globalContext.onServer = globalContext.onServer || true; +globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; + +function seleniumResetInterceptor() { + "use strict"; + 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; + } + }; +} + +function patchServerEnvironment() { + "use strict"; + + 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, @@ -532,19 +617,8 @@ function $X(xpath, contextNode, resultType) { return nodes; } -var globalContext = this; // selbocks name-space (function($$){ - if(globalContext.onServer === true && globalContext.scriptServerPatchApplied !== true) { - globalContext.testCase = {}; - HtmlRunnerTestLoop.prototype.old_initialize = HtmlRunnerTestLoop.prototype.initialize; - HtmlRunnerTestLoop.prototype.initialize = function (htmlTestCase, metrics, seleniumCommandFactory) { - LOG.info("SelBlocks: wrapper to HtmlRunnerTestLoop.initialize."); - this.old_initialize(htmlTestCase, metrics, seleniumCommandFactory); - this.commands = []; - }; - globalContext.scriptServerPatchApplied = true; - } // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: // Global functions are intentional features provided for use by end user's in their Selenium scripts. @@ -749,43 +823,6 @@ var globalContext = this; $$.fn.interceptAfter(Selenium.prototype, "reset", function() { $$.LOG.trace("In tail intercept :: Selenium.reset()"); - if (globalContext.onServer === true) { - //globalContext.scriptInterceptsSeleniumReset = true; - function map_list(list, for_func, if_func) { - var i, - x, - mapped_list = []; - LOG.info("SelBlocks: maplist to get commandrows."); - for (i = 0; i < list.length; ++i) { - x = list[i]; - // AJS: putaquiupariu - if (null == if_func || if_func(i, x)) { - mapped_list.push(for_func(i, x)); - } - } - return mapped_list; - } - if (htmlTestRunner == undefined - || htmlTestRunner == null) { - LOG.info("SelBlocks: Selenium reset pre htmlTestRunner instatiation "); - } else { - LOG.info("SelBlocks: Selenium reset after instatiation of htmlTestRunner.currentTest.htmlTestCase:" + htmlTestRunner.currentTest.htmlTestCase); - //TODO: map commands to real types instead of faking it - htmlTestRunner.currentTest.commands = map_list(htmlTestRunner.currentTest.htmlTestCase.getCommandRows(), function (i, x) { - var b = x.getCommand(); - if (x.hasOwnProperty('trElement')) { - b.type = "command"; - } else { - b.type = "comment"; - } - return b; - }); - // AJS: initializes private testCase (closure) to point to htmlTestRunner.currentTest (public testCase is not available under Core). - testCase = htmlTestRunner.currentTest; - // the debugContext isn't there, but redirecting to the testCase seems to work. - testCase.debugContext = testCase; - } - } try { compileSelBlocks(); } @@ -1857,8 +1894,7 @@ var globalContext = this; } // intercept command processing and simply stop test execution instead of executing the next command if(globalContext.onServer === true) { - $$.fn.interceptOnce(htmlTestRunner.currentTest, "resume", - $$.handleAsExitTest); + $$.fn.interceptOnce(htmlTestRunner.currentTest, "resume", $$.handleAsExitTest); } else { $$.fn.interceptOnce(editor.selDebugger.runner.currentTest, "resume", $$.handleAsExitTest); } From 9abb9c9bbc8d3c4b771420788953207728d0b5e6 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 23 Dec 2014 15:45:53 -0500 Subject: [PATCH 013/116] updated to run tests and open debug on fail The file runTestsOnServer will autorun the html test suite. If the tests timeout or the server fails to launch then the debug environment will open. --- .gitignore | 4 + build/createSelblocksUserExtensions.cmd | 1 + testUserExtension/runTestsOnServer.cmd | 351 ++++++++++++++++++++---- 3 files changed, 304 insertions(+), 52 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..da31fa8 --- /dev/null +++ b/.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/build/createSelblocksUserExtensions.cmd b/build/createSelblocksUserExtensions.cmd index 2645327..9edfcad 100644 --- a/build/createSelblocksUserExtensions.cmd +++ b/build/createSelblocksUserExtensions.cmd @@ -6,3 +6,4 @@ 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 +EXIT /B %ERRORLEVEL% \ No newline at end of file diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index 1a1b134..006684c 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -1,62 +1,309 @@ @ echo off -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 - -SET resultsLog=%~dp0\results -SET serverLog=%~dp0\Selenium Server Log.txt -SET testSuite=%~dp0..\sel-blocksTests\_SelBlocks-TestSuite.html -SET userExtensions=%~dp0\user-extensions.js - -rem creates the user extension with selbench and selblocks -SET selblocksUserExtension=%~dp0..\user extension\user-extensions.js -SET selbenchUserExtension=%~dp0..\..\..\selbench\SelBench\user extension\user-extensions.js -COPY "%selbenchUserExtension%"+"%selblocksUserExtension%" /B "%userExtensions%" /B +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=30 +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=localhost +SET port=4444 +REM the name of the test suite to load into the server +SET testSuiteFileName=_SelBlocks-TestSuite.html +REM directory that holds the selenese tests +SET testsDirName=sel-blocksTests +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\ -REM selenium-server-standalone*.jar, chromedriver.exe, and IEDriverServer.exe -SET seleniumLocation=%~dp0..\..\..\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=%baseURL%/selenium-server/%testsDirName%/%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%\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 -SET baseURL=http://localhost:4444 +CALL :startAutotest "firefox" +IF NOT %ERRORLEVEL% EQU 0 ( + CALL :startDebug +) -rem deletes the existing logs and results -FOR %%I IN ("%serverLog%*") DO DEL /Q "%%I" -FOR %%I IN (results-*.html) DO DEL /Q "%%I" +ENDLOCAL +EXIT /B %ERRORLEVEL% -rem Sets the seleniumServerJar variable to the path of the one with the highest -rem version in the directory pointed at by seleniumLocation -FOR %%I IN (%seleniumLocation%\selenium-server-standalone*.jar) DO SET seleniumServerJar=%%~dpnxI +:cleanupLogsAndResults + SETLOCAL + REM deletes the existing server logs + FOR %%I IN ("%serverLog%*") DO DEL /Q "%%I" -REM runs test suite specified by testSuite, in firefox -SET browser=firefox -start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" -"%resultsLog%-%browser%.html" + REM deletes the existing auto testing results + FOR %%I IN (results-*.html) DO DEL /Q "%%I" +ENDLOCAL +EXIT /B 0 -rem uncomment the following lines once selbench works on the server with firefox. -rem we'll deal with browser inconsistencies after we get things up and running. +:generateTestingUserExtension + SETLOCAL + REM creates the user extension with selbench and selblocks + + SET selbenchUserExtension=%projectRoot%..\..\selbench\SelBench\user extension\user-extensions.js -rem SET browser=piiexplore -rem start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" -rem "%resultsLog%-%browser%.html" -rem SET browser=googlechrome -rem start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" -userExtensions "%userExtensions%" -log "%serverLog%" -browserSideLog -Dwebdriver.ie.driver="%seleniumLocation%\IEDriverServer.exe" -Dwebdriver.chrome.driver="%seleniumLocation%\chromedriver.exe" -htmlSuite "*%browser%" "%baseURL%" "%testSuite%" "%resultsLog%-%browser%.html" -rem "%resultsLog%-%browser%.html" + DEL /Q %testUserExtensions% + + START "Regenerating default user-extensions.js" /WAIT /MIN CMD /C "%projectRoot%\build\createSelblocksUserExtensions.cmd" + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Could not generate user-extensions.js + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + + COPY "%selbenchUserExtension%"+"%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 + REM opens the file in the default application. + IF [%1]==[] ( + ECHO ERROR: No file specified. + ENDLOCAL + EXIT /B 1 + ) + CALL :waitForFile %* + IF NOT %ERRORLEVEL% EQU 0 ( + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + ECHO INFO: Opening %* + explorer %* +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:startAutotest + SETLOCAL + IF [%1]==[] ( + ECHO ERROR: No browser specified. + ENDLOCAL + EXIT /B 1 + ) + SET browser=%~1 + REM firefox, piiexplore, googlechrome + + CALL :cleanupLogsAndResults + IF NOT %ERRORLEVEL% EQU 0 ( + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + CALL :generateTestingUserExtension + IF NOT %ERRORLEVEL% EQU 0 ( + 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 %port% ^ + -Dwebdriver.ie.driver="%seleniumServerLocation%\IEDriverServer.exe" ^ + -Dwebdriver.chrome.driver="%seleniumServerLocation%\chromedriver.exe" ^ + -userExtensions "%testUserExtensions%" ^ + -log "%serverLog%" -browserSideLog ^ + -htmlSuite "*%browser%" "%baseURL%" "%testSuiteFile%" "%resultsLog%-%browser%.html" ^ + -timeout %autotestTimeoutInSeconds% + + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Something went wrong with the server or the tests timed out. Check the logs. + SETLOCAL ENABLEDELAYEDEXPANSION + SET str=%serverLog% + FOR /l %%i in (1,1,10) DO SET str=!str:\\=\! + CALL :openFile "!str!" + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + + REM opens the results in the default browser + CALL :openFile "%resultsLog%-%browser%.html" 3 + IF NOT %ERRORLEVEL% EQU 0 ( + ECHO ERROR: Could not open browser to the test results. + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) +ENDLOCAL +EXIT /B %ERRORLEVEL% + +:startDebug + SETLOCAL + DEL /Q %serverDebugUserExtensions% + + REM copies the testing user extensions file to the debug location. + COPY "user-extensions.js" %serverDebugUserExtensions% + 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 %port% ^ + -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. + + 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=%protocol%%sc%%fs%%fs%%host%%sc%%port%/selenium-server/postResults" + SET "str=%str%&baseUrl=%protocol%%sc%%fs%%fs%%host%%sc%%port%" + SET "str=%str%&multiWindow=true" + 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 + +:seleniumOpenHub +SETLOCAL + explorer "%baseURL%/wd/hub" +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 + +:seleniumOpenSeleniumServer +SETLOCAL + explorer "%baseURL%/selenium-server/" +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 + +:seleniumOpenSeleniumServerDriver +SETLOCAL + explorer "%baseURL%/selenium-server/driver/" +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 + +:seleniumOpenSeleniumServerCore +SETLOCAL + explorer "%baseURL%/selenium-server/core/" +ENDLOCAL +REM explorer sets an errorlevel if it tries to open anything that isn't a file +EXIT /B 0 From aa29c36346e86c2e21762f19ee5e41d4026572cc Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 23 Dec 2014 16:54:40 -0500 Subject: [PATCH 014/116] adds options to debug alternate test suites --- testUserExtension/runTestsOnServer.cmd | 100 +++++++++++++++++++------ 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index 006684c..23b84a7 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -54,11 +54,30 @@ 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 :startAutotest "firefox" -IF NOT %ERRORLEVEL% EQU 0 ( - CALL :startDebug -) + + +IF ["%~1"]==[""] ( + CALL :startAutotest "firefox" + IF NOT %ERRORLEVEL% EQU 0 ( + CALL :startDebugTestSuite + ) +) ELSE IF [%~1]==[start-debug] ( + IF NOT ["%~2"]==[""] ( + echo x + CALL :startDebugTestSuite "%~2" + ) ELSE ( + CALL :startDebugTestSuite + ) +) ELSE IF [%~1]==[open-hub] ( + CALL :seleniumOpenHub +) ELSE IF [%~1]==[open-selenium-server] ( + CALL :seleniumOpenSeleniumServer +) ELSE IF [%~1]==[open-driver] ( + CALL :seleniumOpenSeleniumServerDriver +) ELSE IF [%~1]==[open-core] ( + CALL :seleniumOpenSeleniumServerCore +) ENDLOCAL EXIT /B %ERRORLEVEL% @@ -97,14 +116,14 @@ EXIT /B %ERRORLEVEL% SET /a max=11 SET filename= - IF [%1]==[] ( + IF ["%~1"]==[""] ( ECHO ERROR: No file given to wait for. ENDLOCAL EXIT /B 1 ) ELSE ( SET filename=%~1 ) - IF [%2]==[] ( + IF ["%~2"]==[""] ( ECHO WARNING: No maximum count given, defaulting to %max%. ) ELSE ( SET /a max=%2 @@ -130,7 +149,7 @@ EXIT /B %ERRORLEVEL% :openFile SETLOCAL REM opens the file in the default application. - IF [%1]==[] ( + IF ["%~1"]==[""] ( ECHO ERROR: No file specified. ENDLOCAL EXIT /B 1 @@ -145,9 +164,9 @@ EXIT /B %ERRORLEVEL% ENDLOCAL EXIT /B %ERRORLEVEL% -:startAutotest +:startAutotestServer SETLOCAL - IF [%1]==[] ( + IF ["%~1"]==[""] ( ECHO ERROR: No browser specified. ENDLOCAL EXIT /B 1 @@ -155,17 +174,6 @@ EXIT /B %ERRORLEVEL% SET browser=%~1 REM firefox, piiexplore, googlechrome - CALL :cleanupLogsAndResults - IF NOT %ERRORLEVEL% EQU 0 ( - ENDLOCAL - EXIT /B %ERRORLEVEL% - ) - CALL :generateTestingUserExtension - IF NOT %ERRORLEVEL% EQU 0 ( - ENDLOCAL - EXIT /B %ERRORLEVEL% - ) - REM browsers currently available REM *firefox @@ -197,11 +205,40 @@ EXIT /B %ERRORLEVEL% -log "%serverLog%" -browserSideLog ^ -htmlSuite "*%browser%" "%baseURL%" "%testSuiteFile%" "%resultsLog%-%browser%.html" ^ -timeout %autotestTimeoutInSeconds% + +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 + + CALL :cleanupLogsAndResults + IF NOT %ERRORLEVEL% EQU 0 ( + ENDLOCAL + EXIT /B %ERRORLEVEL% + ) + + 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. 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 @@ -218,7 +255,7 @@ EXIT /B %ERRORLEVEL% ENDLOCAL EXIT /B %ERRORLEVEL% -:startDebug +:startDebugServer SETLOCAL DEL /Q %serverDebugUserExtensions% @@ -243,6 +280,17 @@ EXIT /B %ERRORLEVEL% 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=%baseURL%/selenium-server/%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. @@ -257,7 +305,7 @@ EXIT /B %ERRORLEVEL% :seleniumOpenTestSuite SETLOCAL - IF [%1]==[] ( + IF ["%~1"]==[""] ( ECHO ERROR: No test specified. ENDLOCAL EXIT /B 1 @@ -271,8 +319,8 @@ SETLOCAL SET "str=%str%&multiWindow=true" SET "str=%str%&defaultLogLevel=info" - IF NOT [%2]==[] ( - SET str=%str%^&auto=true + IF NOT ["%~2"]==[""] ( + SET "str=%str%&auto=true" ) explorer "%str%" @@ -282,6 +330,7 @@ EXIT /B 0 :seleniumOpenHub SETLOCAL + CALL :startDebugServer explorer "%baseURL%/wd/hub" ENDLOCAL REM explorer sets an errorlevel if it tries to open anything that isn't a file @@ -289,6 +338,7 @@ EXIT /B 0 :seleniumOpenSeleniumServer SETLOCAL + CALL :startDebugServer explorer "%baseURL%/selenium-server/" ENDLOCAL REM explorer sets an errorlevel if it tries to open anything that isn't a file @@ -296,6 +346,7 @@ EXIT /B 0 :seleniumOpenSeleniumServerDriver SETLOCAL + CALL :startDebugServer explorer "%baseURL%/selenium-server/driver/" ENDLOCAL REM explorer sets an errorlevel if it tries to open anything that isn't a file @@ -303,6 +354,7 @@ EXIT /B 0 :seleniumOpenSeleniumServerCore SETLOCAL + CALL :startDebugServer explorer "%baseURL%/selenium-server/core/" ENDLOCAL REM explorer sets an errorlevel if it tries to open anything that isn't a file From a40fbcc12abe9b4c3559481eea28b3f7f84a1e0c Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 23 Dec 2014 17:06:50 -0500 Subject: [PATCH 015/116] adds options to start autotest on other browsers --- testUserExtension/runTestsOnServer.cmd | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index 23b84a7..d2b998d 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -62,9 +62,20 @@ IF ["%~1"]==[""] ( IF NOT %ERRORLEVEL% EQU 0 ( CALL :startDebugTestSuite ) +) ELSE IF [%~1]==[start-autotest] ( + IF NOT ["%~2"]==[""] ( + CALL :startAutotest "%~2" + IF NOT %ERRORLEVEL% EQU 0 ( + CALL :startDebugTestSuite + ) + ) ELSE ( + CALL :startAutotest "firefox" + IF NOT %ERRORLEVEL% EQU 0 ( + CALL :startDebugTestSuite + ) + ) ) ELSE IF [%~1]==[start-debug] ( IF NOT ["%~2"]==[""] ( - echo x CALL :startDebugTestSuite "%~2" ) ELSE ( CALL :startDebugTestSuite @@ -170,6 +181,8 @@ EXIT /B %ERRORLEVEL% 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 @@ -241,8 +254,7 @@ EXIT /B %ERRORLEVEL% 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% + ENDLOCAL & EXIT /B %ERRORLEVEL% ) REM opens the results in the default browser From 7cc23fbfac1a291656e15e89482751b2cc23ccc8 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 23 Dec 2014 21:44:01 -0500 Subject: [PATCH 016/116] adds parameter handler, help text, & awesome somewhere along the way I broke the default action of opening up the tests in the default browser for debugging. I fixed that. I fixed everything. This is a pretty sweet launcher. --- testUserExtension/runTestsOnServer.cmd | 160 +++++++++++++++++-------- 1 file changed, 112 insertions(+), 48 deletions(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index d2b998d..0fc5a31 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -54,44 +54,92 @@ 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% - - -IF ["%~1"]==[""] ( - CALL :startAutotest "firefox" - IF NOT %ERRORLEVEL% EQU 0 ( - CALL :startDebugTestSuite - ) -) ELSE IF [%~1]==[start-autotest] ( - IF NOT ["%~2"]==[""] ( - CALL :startAutotest "%~2" - IF NOT %ERRORLEVEL% EQU 0 ( +: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 ( - CALL :startAutotest "firefox" - IF NOT %ERRORLEVEL% EQU 0 ( + ) 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]==[start-debug] ( - IF NOT ["%~2"]==[""] ( - CALL :startDebugTestSuite "%~2" + ) 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 ( - CALL :startDebugTestSuite + ECHO ERROR: I don't know what you want to do. + ECHO ERROR: %* ) -) ELSE IF [%~1]==[open-hub] ( - CALL :seleniumOpenHub -) ELSE IF [%~1]==[open-selenium-server] ( - CALL :seleniumOpenSeleniumServer -) ELSE IF [%~1]==[open-driver] ( - CALL :seleniumOpenSeleniumServerDriver -) ELSE IF [%~1]==[open-core] ( - CALL :seleniumOpenSeleniumServerCore -) 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. + 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 @@ -222,6 +270,16 @@ EXIT /B %ERRORLEVEL% 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"]==[""] ( @@ -232,6 +290,13 @@ EXIT /B %ERRORLEVEL% ) REM firefox, piiexplore, googlechrome + IF ["%~2"]==["nolog"] ( + ECHO WARN: Will not open Server Log on failure. + SET nolog=true + ) ELSE ( + SET nolog=false + ) + CALL :cleanupLogsAndResults IF NOT %ERRORLEVEL% EQU 0 ( ENDLOCAL @@ -245,16 +310,15 @@ 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. - 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% + IF %nolog%==true ( + ECHO INFO: Logs can be found at: %serverLog% + ) ELSE ( + CALL :openServerLog + ) + ENDLOCAL + EXIT /B 1 ) REM opens the results in the default browser @@ -262,7 +326,7 @@ EXIT /B %ERRORLEVEL% IF NOT %ERRORLEVEL% EQU 0 ( ECHO ERROR: Could not open browser to the test results. ENDLOCAL - EXIT /B %ERRORLEVEL% + EXIT /B 1 ) ENDLOCAL EXIT /B %ERRORLEVEL% @@ -340,26 +404,26 @@ ENDLOCAL REM explorer sets an errorlevel if it tries to open anything that isn't a file EXIT /B 0 -:seleniumOpenHub -SETLOCAL - CALL :startDebugServer - explorer "%baseURL%/wd/hub" -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/" + 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 - explorer "%baseURL%/selenium-server/driver/" + 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 @@ -367,7 +431,7 @@ EXIT /B 0 :seleniumOpenSeleniumServerCore SETLOCAL CALL :startDebugServer - explorer "%baseURL%/selenium-server/core/" + 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 From 13c22e779c14df609c4627c2b99e22f4c20c772b Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 23 Dec 2014 21:48:52 -0500 Subject: [PATCH 017/116] added note about testing in all browsers at once I had forgotten to write this in the help text. --- testUserExtension/runTestsOnServer.cmd | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index 0fc5a31..9a1b4e1 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -115,7 +115,13 @@ SETLOCAL 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. + 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 From 8c34856fddff6cd355c4d596b364862691d193da Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 23 Dec 2014 22:33:37 -0500 Subject: [PATCH 018/116] refactoring for reuse in selbench I think I've got it down to only changing three of the variables at the top of the script, to port this over to selbench. --- testUserExtension/runTestsOnServer.cmd | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index 9a1b4e1..1fa3fe3 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -14,8 +14,15 @@ SET host=localhost SET port=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 @@ -158,20 +165,20 @@ EXIT /B 0 :generateTestingUserExtension SETLOCAL - REM creates the user extension with selbench and selblocks + REM creates the user extension with selbench - SET selbenchUserExtension=%projectRoot%..\..\selbench\SelBench\user extension\user-extensions.js - DEL /Q %testUserExtensions% - START "Regenerating default user-extensions.js" /WAIT /MIN CMD /C "%projectRoot%\build\createSelblocksUserExtensions.cmd" + 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% ) - COPY "%selbenchUserExtension%"+"%defaultUserExtensions%" /B "%testUserExtensions%" /B + IF DEFINED selbenchUserExtension ( + COPY "%selbenchUserExtension%"+"%defaultUserExtensions%" /B "%testUserExtensions%" /B + ) ENDLOCAL EXIT /B %ERRORLEVEL% @@ -342,7 +349,7 @@ EXIT /B %ERRORLEVEL% DEL /Q %serverDebugUserExtensions% REM copies the testing user extensions file to the debug location. - COPY "user-extensions.js" %serverDebugUserExtensions% + COPY "%testUserExtensions%" /B "%serverDebugUserExtensions%" /B IF NOT %ERRORLEVEL% EQU 0 ( ECHO ERROR: Could not copy user-extensions.js to the project root. ENDLOCAL From 4e5172332a99b7120d9f9fe9a02ce8291ebd2710 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 23 Dec 2014 23:30:47 -0500 Subject: [PATCH 019/116] minor tweaks --- build/createSelblocksUserExtensions.cmd | 3 ++- testUserExtension/runTestsOnServer.cmd | 34 +++++++++++++++---------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/build/createSelblocksUserExtensions.cmd b/build/createSelblocksUserExtensions.cmd index 9edfcad..c264e96 100644 --- a/build/createSelblocksUserExtensions.cmd +++ b/build/createSelblocksUserExtensions.cmd @@ -1,9 +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/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index 1fa3fe3..b55ecb9 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -4,7 +4,7 @@ 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=30 +SET /a autotestTimeoutInSeconds=90 REM the root of the project REM C:\projects\selenium\selblocks\SelBlocks\ SET projectRoot=%~dp0..\ @@ -178,6 +178,8 @@ EXIT /B 0 IF DEFINED selbenchUserExtension ( COPY "%selbenchUserExtension%"+"%defaultUserExtensions%" /B "%testUserExtensions%" /B + ) ELSE ( + COPY "%defaultUserExtensions%" /B "%testUserExtensions%" /B ) ENDLOCAL EXIT /B %ERRORLEVEL% @@ -219,20 +221,24 @@ ENDLOCAL EXIT /B %ERRORLEVEL% :openFile - SETLOCAL + SETLOCAL ENABLEDELAYEDEXPANSION REM opens the file in the default application. IF ["%~1"]==[""] ( ECHO ERROR: No file specified. ENDLOCAL EXIT /B 1 ) - CALL :waitForFile %* + 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 %* - explorer %* + ECHO INFO: Opening "!str!" + explorer "!str!" ENDLOCAL EXIT /B %ERRORLEVEL% @@ -330,16 +336,18 @@ EXIT /B %ERRORLEVEL% ) ELSE ( CALL :openServerLog ) - ENDLOCAL - EXIT /B 1 ) - REM opens the results in the default browser - CALL :openFile "%resultsLog%-%browser%.html" 3 - IF NOT %ERRORLEVEL% EQU 0 ( - ECHO ERROR: Could not open browser to the test results. - ENDLOCAL - EXIT /B 1 + 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% From c9c581c9721294fc19689a75f1d8671db4e235ca Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 25 Dec 2014 01:49:03 -0500 Subject: [PATCH 020/116] breaking down the if tests --- sel-blocksTests/_SelBlocks-TestSuite.html | 4 +- sel-blocksTests/if-1.html | 234 ++++++++++++++++++++++ sel-blocksTests/if-2.html | 187 +++++++++++++++++ sel-blocksTests/if-3.html | 93 +++++++++ 4 files changed, 517 insertions(+), 1 deletion(-) create mode 100644 sel-blocksTests/if-1.html create mode 100644 sel-blocksTests/if-2.html create mode 100644 sel-blocksTests/if-3.html diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 62bf455..302fe62 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -11,7 +11,9 @@ README eval branching -if +if-1 +if-2 +if-3 try while for 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"
+ + From 30e556f4315b1caff383942ab47e2ac85d848706 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 00:29:30 -0500 Subject: [PATCH 021/116] removing strict mode There's a lot of code in this extension that relies on strict mode being off. --- user extension/scripts/config.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/user extension/scripts/config.js b/user extension/scripts/config.js index 41774fe..7ca7625 100644 --- a/user extension/scripts/config.js +++ b/user extension/scripts/config.js @@ -4,17 +4,17 @@ maxerr:500, plusplus:true */ /*globals -selblocks, -HtmlRunnerTestLoop, -Selenium, -htmlTestRunner +globalContext:true, +HtmlRunnerTestLoop:true, +Selenium:true, +htmlTestRunner:true */ -var globalContext = this; +globalContext = this; globalContext.onServer = globalContext.onServer || true; globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; + function seleniumResetInterceptor() { - "use strict"; var old_reset; old_reset = Selenium.prototype.reset; @@ -59,7 +59,6 @@ function seleniumResetInterceptor() { } function patchServerEnvironment() { - "use strict"; if (globalContext.scriptServerPatchApplied !== true) { globalContext.testCase = {}; From e7f6f438a517445d194eaec85bbcfa24f4490797 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 00:32:11 -0500 Subject: [PATCH 022/116] throwing errors in isManaged returns false interceptFrame.attrs doesn't always exist. There won't be an error manager in that case and, the test blows up. I'm just catching that error and returning false from isManaged, since the error isn't managed. --- .../selenium-executionloop-handleAsTryBlock.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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; } }; From c144f36e2b232800108e762a2bfca1b88fa83e10 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 00:34:27 -0500 Subject: [PATCH 023/116] removing patch to setNextCommand This was breaking everything, so I took it out. It was only used on the server and only broke things on the server... --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index b8a99f1..5db4601 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -272,9 +272,6 @@ function $X(xpath, contextNode, resultType) { assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, " Cannot branch to non-existent command @" + (cmdIdx+1)); branchIdx = cmdIdx; - if(globalContext.onServer === true) { - testCase.htmlTestCase.nextCommandRowIndex = cmdIdx; // w/o branching - } } // Selenium calls reset(): From 1ae3354fb03c9de58aa22e8ca7ea40eadd1f85fb Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 00:35:27 -0500 Subject: [PATCH 024/116] rebuilds user extension with latest selbench I've updated the user-extension for selbench as well. They go together. --- user extension/user-extensions.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 192d7e9..aa1b5fb 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -4,17 +4,17 @@ maxerr:500, plusplus:true */ /*globals -selblocks, -HtmlRunnerTestLoop, -Selenium, -htmlTestRunner +globalContext:true, +HtmlRunnerTestLoop:true, +Selenium:true, +htmlTestRunner:true */ -var globalContext = this; +globalContext = this; globalContext.onServer = globalContext.onServer || true; globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; + function seleniumResetInterceptor() { - "use strict"; var old_reset; old_reset = Selenium.prototype.reset; @@ -59,7 +59,6 @@ function seleniumResetInterceptor() { } function patchServerEnvironment() { - "use strict"; if (globalContext.scriptServerPatchApplied !== true) { globalContext.testCase = {}; @@ -528,10 +527,17 @@ globalContext = this; 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; } }; @@ -810,9 +816,6 @@ function $X(xpath, contextNode, resultType) { assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, " Cannot branch to non-existent command @" + (cmdIdx+1)); branchIdx = cmdIdx; - if(globalContext.onServer === true) { - testCase.htmlTestCase.nextCommandRowIndex = cmdIdx; // w/o branching - } } // Selenium calls reset(): From c90d591b157867ca9d967f7a522347804aafb1a5 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 01:20:30 -0500 Subject: [PATCH 025/116] updates readme test to fetch an accessible page --- sel-blocksTests/README.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 0bbac86387324f782dc38503808f6f48bcb0801e Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 02:44:47 -0500 Subject: [PATCH 026/116] fix typo in error handler for server "try" --- user extension/user-extensions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index aa1b5fb..a216567 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -1271,7 +1271,7 @@ function $X(xpath, contextNode, resultType) { // enable special command handling if(globalContext.onServer === true) { $$.fn.interceptPush(htmlTestRunner.currentTest, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); + $$.handleAsTryBlock, { manageError: handleCommandError }); } else { $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", $$.handleAsTryBlock, { manageError: handleCommandError }); From 68f3502464f589fc7c74f216d23314a0f3a6f8ad Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 02:45:27 -0500 Subject: [PATCH 027/116] server "try" error handler fix --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 5db4601..4f45ed0 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -727,7 +727,7 @@ function $X(xpath, contextNode, resultType) { // enable special command handling if(globalContext.onServer === true) { $$.fn.interceptPush(htmlTestRunner.currentTest, "resume", - $$.handleAsTryBlock, { handleError: handleCommandError }); + $$.handleAsTryBlock, { manageError: handleCommandError }); } else { $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", $$.handleAsTryBlock, { manageError: handleCommandError }); From 389ae42950ce7db54342e53f0b60f083ba3ab279 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 03:59:04 -0500 Subject: [PATCH 028/116] set firefox's proxy to localhost:4444 the automatic script won't be automatic unless you set your browser to use the selenium server as its proxy. --- testUserExtension/runTestsOnServer.cmd | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index b55ecb9..df3be8d 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -10,8 +10,10 @@ 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=localhost -SET port=4444 +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 @@ -47,7 +49,7 @@ 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=%baseURL%/selenium-server/%testsDirName%/%testSuiteFileName% +SET testSuiteURL=./../%testsDirName%/%testSuiteFileName% REM the release version of the user extension. SET defaultUserExtensions=%projectRoot%\%userExtensionDirName%\user-extensions.js REM the testing version of the user extension. @@ -278,7 +280,7 @@ EXIT /B %ERRORLEVEL% REM runs test suite specified by testSuiteFile, in the given browser start /wait "selenium server" /MIN java -jar "%seleniumServerJar%" ^ - -port %port% ^ + -port %seleniumServerPort% ^ -Dwebdriver.ie.driver="%seleniumServerLocation%\IEDriverServer.exe" ^ -Dwebdriver.chrome.driver="%seleniumServerLocation%\chromedriver.exe" ^ -userExtensions "%testUserExtensions%" ^ @@ -369,7 +371,7 @@ EXIT /B %ERRORLEVEL% 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 %port% ^ + -port %seleniumServerPort% ^ -Dwebdriver.ie.driver="%seleniumServerLocation%\IEDriverServer.exe" ^ -Dwebdriver.chrome.driver="%seleniumServerLocation%\chromedriver.exe" ^ -userExtensions "%serverDebugUserExtensions%" ^ @@ -384,7 +386,7 @@ EXIT /B %ERRORLEVEL% SETLOCAL REM alternate test suites may be specified IF NOT ["%~1"]==[""] ( - SET "testSuiteURL=%baseURL%/selenium-server/%testsDirName%/%~1" + SET "testSuiteURL=./../%testsDirName%/%~1" ) CALL :startDebugServer @@ -411,9 +413,9 @@ SETLOCAL SET sc=%%3A SET fs=%%2F SET "str=%baseURL%/selenium-server/core/TestRunner.html?test=%~1" - SET "str=%str%&resultsUrl=%protocol%%sc%%fs%%fs%%host%%sc%%port%/selenium-server/postResults" + SET "str=%str%&resultsUrl=./selenium-server/postResults" SET "str=%str%&baseUrl=%protocol%%sc%%fs%%fs%%host%%sc%%port%" - SET "str=%str%&multiWindow=true" + SET "str=%str%&multiWindow=on" SET "str=%str%&defaultLogLevel=info" IF NOT ["%~2"]==[""] ( From decefc369b7bd9c07a310d71557587c6ff702908 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 23:39:52 -0500 Subject: [PATCH 029/116] Moved server root for debug tests When giving the server an html suite to run automatically, it will root there. This overrides setting the server root by placement of the user-extensions.js file. To make file paths consistent between automatic and debug tests, I moved the location of the debug copy of the user script into the sel-blocksTests folder. --- .../chrome/content/extensions/selblocks.js | 77 +++++++++++++++---- .gitignore => sel-blocksTests/.gitignore | 0 testUserExtension/runTestsOnServer.cmd | 16 +++- 3 files changed, 77 insertions(+), 16 deletions(-) rename .gitignore => sel-blocksTests/.gitignore (100%) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 4f45ed0..415b25e 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -237,12 +237,6 @@ function $X(xpath, contextNode, resultType) { // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) function nextCommand() { - if(globalContext.onServer === true) { - this._advanceToNextRow(); - if (this.currentRow == null) { - return null; - } - } if (!this.started) { this.started = true; this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; @@ -257,8 +251,29 @@ function $X(xpath, contextNode, resultType) { this.debugIndex++; } } + // skip over comments while (this.debugIndex < testCase.commands.length) { + // we're just incrementing the index by 1 until we find the next command + // on the server, the _advanceToNextRow does that and a couple other + // things that are apparently necessary on the server. The debugIndex and + // nextCommandRowIndex mean the same thing between the IDE and server, + // so I turned them both into pseudo properties with getters/setters + // that point to a hidden property. They'll both always have the same value. + // only reason I'm not changing this to an intercept and using the original + // nextCommand when on the server is because the selblocks compile + // function relies on the commands array. I don't know if there's some + // underlying collection existing on both the server and IDE that could be + // used instead. + if(globalContext.onServer === true) { + this._advanceToNextRow(); + // _advanceToNextRow could set the current row null, it only gets + // command rows. No point in continuing if that's the case, because + // we've run out of commands. + if (this.currentRow == null) { + return null; + } + } var command = testCase.commands[this.debugIndex]; if (command.type === "command") { this.runTimeStamp = Date.now(); @@ -268,6 +283,11 @@ function $X(xpath, contextNode, resultType) { } 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)); @@ -299,13 +319,17 @@ 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() { blockDefs = new BlockDefs(); @@ -509,7 +533,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); @@ -522,7 +548,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--) { @@ -1518,7 +1546,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); @@ -1612,7 +1649,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); @@ -1715,7 +1761,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/.gitignore b/sel-blocksTests/.gitignore similarity index 100% rename from .gitignore rename to sel-blocksTests/.gitignore diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index df3be8d..d4219b1 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -49,14 +49,14 @@ 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=./../%testsDirName%/%testSuiteFileName% +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%\user-extensions.js +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 @@ -256,6 +256,16 @@ EXIT /B %ERRORLEVEL% 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 @@ -283,7 +293,7 @@ EXIT /B %ERRORLEVEL% -port %seleniumServerPort% ^ -Dwebdriver.ie.driver="%seleniumServerLocation%\IEDriverServer.exe" ^ -Dwebdriver.chrome.driver="%seleniumServerLocation%\chromedriver.exe" ^ - -userExtensions "%testUserExtensions%" ^ + -userExtensions "%serverDebugUserExtensions%" ^ -log "%serverLog%" -browserSideLog ^ -htmlSuite "*%browser%" "%baseURL%" "%testSuiteFile%" "%resultsLog%-%browser%.html" ^ -timeout %autotestTimeoutInSeconds% From 35e8f0796097faea79c1133a22dca087dcd4b755 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 23:41:32 -0500 Subject: [PATCH 030/116] Updates server patch, now passing all but 2 tests The only tests that are still failing on the server are the "try" and "continue-break" tests. We can use forJson and forXml now. --- user extension/scripts/config.js | 25 +++++++- user extension/user-extensions.js | 103 +++++++++++++++++++++++++----- 2 files changed, 112 insertions(+), 16 deletions(-) diff --git a/user extension/scripts/config.js b/user extension/scripts/config.js index 7ca7625..5cd0854 100644 --- a/user extension/scripts/config.js +++ b/user extension/scripts/config.js @@ -13,7 +13,7 @@ globalContext = this; globalContext.onServer = globalContext.onServer || true; globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; - +(function () { function seleniumResetInterceptor() { var old_reset; old_reset = Selenium.prototype.reset; @@ -54,6 +54,28 @@ function seleniumResetInterceptor() { 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; } }; } @@ -78,3 +100,4 @@ function patchServerEnvironment() { 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 index a216567..85b1add 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -13,7 +13,7 @@ globalContext = this; globalContext.onServer = globalContext.onServer || true; globalContext.serverPatchApplied = globalContext.serverPatchApplied || false; - +(function () { function seleniumResetInterceptor() { var old_reset; old_reset = Selenium.prototype.reset; @@ -54,6 +54,28 @@ function seleniumResetInterceptor() { 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; } }; } @@ -78,7 +100,7 @@ function patchServerEnvironment() { if ((globalContext.onServer === true) && (globalContext.serverPatchApplied === false)) { patchServerEnvironment(); } -// SelBlocks name-space +}());// SelBlocks name-space var selblocks = { name: "SelBlocks" }; // I don't want to redeclare the variable when the user-extension is generated @@ -781,12 +803,6 @@ function $X(xpath, contextNode, resultType) { // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) function nextCommand() { - if(globalContext.onServer === true) { - this._advanceToNextRow(); - if (this.currentRow == null) { - return null; - } - } if (!this.started) { this.started = true; this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; @@ -801,8 +817,29 @@ function $X(xpath, contextNode, resultType) { this.debugIndex++; } } + // skip over comments while (this.debugIndex < testCase.commands.length) { + // we're just incrementing the index by 1 until we find the next command + // on the server, the _advanceToNextRow does that and a couple other + // things that are apparently necessary on the server. The debugIndex and + // nextCommandRowIndex mean the same thing between the IDE and server, + // so I turned them both into pseudo properties with getters/setters + // that point to a hidden property. They'll both always have the same value. + // only reason I'm not changing this to an intercept and using the original + // nextCommand when on the server is because the selblocks compile + // function relies on the commands array. I don't know if there's some + // underlying collection existing on both the server and IDE that could be + // used instead. + if(globalContext.onServer === true) { + this._advanceToNextRow(); + // _advanceToNextRow could set the current row null, it only gets + // command rows. No point in continuing if that's the case, because + // we've run out of commands. + if (this.currentRow == null) { + return null; + } + } var command = testCase.commands[this.debugIndex]; if (command.type === "command") { this.runTimeStamp = Date.now(); @@ -812,6 +849,11 @@ function $X(xpath, contextNode, resultType) { } 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)); @@ -843,13 +885,17 @@ 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() { blockDefs = new BlockDefs(); @@ -1053,7 +1099,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); @@ -1066,7 +1114,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--) { @@ -2062,7 +2112,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); @@ -2156,7 +2215,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); @@ -2259,7 +2327,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); From 6da714d3656bf7c1bf05c6c4d8d7adbe02b58b0a Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 27 Dec 2014 23:46:16 -0500 Subject: [PATCH 031/116] added paths for testing file ops on the server The IDE loads the test suite and sets the current working directory to wherever you loaded the test suite from, I think. That might be a function of the path manipulations done as well. I don't manipulate the URL given to forJson and forXml, since data could exist anywhere on the internet and the browser will resolve the url anyway. --- sel-blocksTests/continue-break.html | 27 ++++++++++++++++++++- sel-blocksTests/forjson.html | 33 +++++++++++++++++++++---- sel-blocksTests/forxml.html | 37 ++++++++++++++++++++++++----- 3 files changed, 86 insertions(+), 11 deletions(-) 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/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" From 0441a200764c418e35c30ac5b3374bee462dfeb9 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 29 Dec 2014 19:50:11 -0500 Subject: [PATCH 032/116] breaks up the continue break test this is failing somewhere but it's too confusing to look at --- sel-blocksTests/_SelBlocks-TestSuite.html | 5 +- sel-blocksTests/continue-break 1.html | 113 ++++++++++++++++++++++ sel-blocksTests/continue-break 2.html | 58 +++++++++++ sel-blocksTests/continue-break 3.html | 53 ++++++++++ sel-blocksTests/continue-break 4.html | 58 +++++++++++ 5 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 sel-blocksTests/continue-break 1.html create mode 100644 sel-blocksTests/continue-break 2.html create mode 100644 sel-blocksTests/continue-break 3.html create mode 100644 sel-blocksTests/continue-break 4.html diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 848aede..def22b4 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -42,7 +42,10 @@ foreach-xpath forjson forxml -continue-break +continue-break 1 +continue-break 2 +continue-break 3 +continue-break 4 nested-loops function function-recursive diff --git a/sel-blocksTests/continue-break 1.html b/sel-blocksTests/continue-break 1.html new file mode 100644 index 0000000..b011426 --- /dev/null +++ b/sel-blocksTests/continue-break 1.html @@ -0,0 +1,113 @@ + + + + + + +continue-break 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 1
ifglobalContext.onServer === true
store../data/forxml.xmlforXmlFileName
else
storedata/forxml.xmlforXmlFileName
endIf
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..49f06df --- /dev/null +++ b/sel-blocksTests/continue-break 4.html @@ -0,0 +1,58 @@ + + + + + + +continue-break 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 4
resetEmitted
forXml${forXmlFileName}
continuexname=="dogbert"
breakxname=="wally"
emit"iter=${xname}"
endForXml
assertEmitted"iter=dilbert"
resetEmitted
+ + From 3ef815bb32378b0a2de7d01ff42a3e9841cc3b6d Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 29 Dec 2014 19:58:23 -0500 Subject: [PATCH 033/116] moves storing path to test case that needs it when I broke up the continue-break test, I didn't move the store command at the top into the test case where it is used. It works when running the full suite but, I can't run the individual test without it. --- sel-blocksTests/continue-break 1.html | 26 ---------------------- sel-blocksTests/continue-break 4.html | 31 +++++++++++++++++++++------ 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/sel-blocksTests/continue-break 1.html b/sel-blocksTests/continue-break 1.html index b011426..e38c96d 100644 --- a/sel-blocksTests/continue-break 1.html +++ b/sel-blocksTests/continue-break 1.html @@ -11,31 +11,6 @@ continue-break 1 - - if - globalContext.onServer === true - - - - store - ../data/forxml.xml - forXmlFileName - - - else - - - - - store - data/forxml.xml - forXmlFileName - - - endIf - - - resetEmitted @@ -107,7 +82,6 @@ "iter=3~iter=4~iter=5" - diff --git a/sel-blocksTests/continue-break 4.html b/sel-blocksTests/continue-break 4.html index 49f06df..164815b 100644 --- a/sel-blocksTests/continue-break 4.html +++ b/sel-blocksTests/continue-break 4.html @@ -16,6 +16,31 @@ + + if + globalContext.onServer === true + + + + store + ../data/forxml.xml + forXmlFileName + + + else + + + + + store + data/forxml.xml + forXmlFileName + + + endIf + + + forXml ${forXmlFileName} @@ -47,12 +72,6 @@ "iter=dilbert" - - resetEmitted - - - - From 452f3f11453cd388ae366d1c208fd676325c9eff Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 29 Dec 2014 20:49:01 -0500 Subject: [PATCH 034/116] executes all command rows now There was a bug giving bad results before. The last few commands of each test case were not being executed, so basically the assertions weren't being asserted and the tests were passing because most of the commands executed. --- .../chrome/content/extensions/selblocks.js | 30 ++++++++----------- user extension/user-extensions.js | 30 ++++++++----------- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 415b25e..3c6870c 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -252,35 +252,29 @@ function $X(xpath, contextNode, resultType) { } } + var command; // skip over comments while (this.debugIndex < testCase.commands.length) { - // we're just incrementing the index by 1 until we find the next command - // on the server, the _advanceToNextRow does that and a couple other - // things that are apparently necessary on the server. The debugIndex and - // nextCommandRowIndex mean the same thing between the IDE and server, - // so I turned them both into pseudo properties with getters/setters - // that point to a hidden property. They'll both always have the same value. - // only reason I'm not changing this to an intercept and using the original - // nextCommand when on the server is because the selblocks compile - // function relies on the commands array. I don't know if there's some - // underlying collection existing on both the server and IDE that could be - // used instead. + command = testCase.commands[this.debugIndex]; + if(globalContext.onServer === true) { - this._advanceToNextRow(); - // _advanceToNextRow could set the current row null, it only gets - // command rows. No point in continuing if that's the case, because - // we've run out of commands. - if (this.currentRow == null) { - return null; + this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; + if (this.sejsElement) { + this.currentItem = agenda.pop(); + this.currentRowIndex = this.debugIndex; } } - var command = testCase.commands[this.debugIndex]; if (command.type === "command") { this.runTimeStamp = Date.now(); return command; } this.debugIndex++; } + + if(globalContext.onServer === true) { + this.currentRow = null; + this.currentItem = null; + } return null; } /** diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 85b1add..fcb48f9 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -818,35 +818,29 @@ function $X(xpath, contextNode, resultType) { } } + var command; // skip over comments while (this.debugIndex < testCase.commands.length) { - // we're just incrementing the index by 1 until we find the next command - // on the server, the _advanceToNextRow does that and a couple other - // things that are apparently necessary on the server. The debugIndex and - // nextCommandRowIndex mean the same thing between the IDE and server, - // so I turned them both into pseudo properties with getters/setters - // that point to a hidden property. They'll both always have the same value. - // only reason I'm not changing this to an intercept and using the original - // nextCommand when on the server is because the selblocks compile - // function relies on the commands array. I don't know if there's some - // underlying collection existing on both the server and IDE that could be - // used instead. + command = testCase.commands[this.debugIndex]; + if(globalContext.onServer === true) { - this._advanceToNextRow(); - // _advanceToNextRow could set the current row null, it only gets - // command rows. No point in continuing if that's the case, because - // we've run out of commands. - if (this.currentRow == null) { - return null; + this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; + if (this.sejsElement) { + this.currentItem = agenda.pop(); + this.currentRowIndex = this.debugIndex; } } - var command = testCase.commands[this.debugIndex]; if (command.type === "command") { this.runTimeStamp = Date.now(); return command; } this.debugIndex++; } + + if(globalContext.onServer === true) { + this.currentRow = null; + this.currentItem = null; + } return null; } /** From 04efc59842143d343d0f619d48e3a51686650bc3 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 00:38:57 -0500 Subject: [PATCH 035/116] Passing all tests XD no for real this time. The server extension is working just like the IDE extension. XD --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 2 ++ user extension/user-extensions.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 3c6870c..c7dc33d 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -259,6 +259,8 @@ function $X(xpath, contextNode, resultType) { if(globalContext.onServer === true) { this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; + command = this.currentRow.getCommand(); + command.type = "command"; if (this.sejsElement) { this.currentItem = agenda.pop(); this.currentRowIndex = this.debugIndex; diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index fcb48f9..41931a3 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -825,6 +825,8 @@ function $X(xpath, contextNode, resultType) { if(globalContext.onServer === true) { this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; + command = this.currentRow.getCommand(); + command.type = "command"; if (this.sejsElement) { this.currentItem = agenda.pop(); this.currentRowIndex = this.debugIndex; From 6968af4ec5e727d9e4cf3d28c872b17ec7029572 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 00:40:43 -0500 Subject: [PATCH 036/116] Breaking up the exit tests --- sel-blocksTests/_SelBlocks-TestSuite.html | 4 +- sel-blocksTests/exitTest - base case.html | 32 ++++++++++++++ .../exitTest - from within a function.html | 43 +++++++++++++++++++ .../exitTest - from within a loop.html | 43 +++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 sel-blocksTests/exitTest - base case.html create mode 100644 sel-blocksTests/exitTest - from within a function.html create mode 100644 sel-blocksTests/exitTest - from within a loop.html diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index def22b4..1794943 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -50,7 +50,9 @@ function function-recursive issue-2-function -exitTest +exitTest - base case +exitTest - from within a loop +exitTest - from within a function 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..f8ef6cc --- /dev/null +++ b/sel-blocksTests/exitTest - from within a loop.html @@ -0,0 +1,43 @@ + + + + + + +exitTest - from within a loop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
exitTest - from within a loop
fori=0; i < 5; i++
ifi == 3
exitTest
endIf
endFor
+ + From 2d10fd19f3af6399852d7975a2a261f9affb4595 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 00:52:39 -0500 Subject: [PATCH 037/116] exitTest now throws on failure All the rows were highlighted in green after this test finished. They should be, yes, but I couldn't tell if the test passed falsely. I added a throw into it that should never be executed, just to make sure. --- .../exitTest - from within a loop.html | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sel-blocksTests/exitTest - from within a loop.html b/sel-blocksTests/exitTest - from within a loop.html index f8ef6cc..6ef3a30 100644 --- a/sel-blocksTests/exitTest - from within a loop.html +++ b/sel-blocksTests/exitTest - from within a loop.html @@ -32,12 +32,26 @@ + + if + i === 3 + + + + throw + "This test should exit when the increment gets to 3, and this should never be thrown." + + + + endIf + + + endFor - From e6459909734afc39f41dba3703da536e3119de69 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 01:54:25 -0500 Subject: [PATCH 038/116] Adds a simple Selenese runner example Users can just edit this with their own paths to get up and running in just a minute or two. --- user extension/SeleniumHTMLRunner.cmd | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 user extension/SeleniumHTMLRunner.cmd 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 From 1af4a756f46f31bbcd1c9863711c43b27a9d9703 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 01:56:19 -0500 Subject: [PATCH 039/116] Updates the readme: about user-extensions.js --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 01c9f66..c6549fe 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ SelBlocks 2 ========= -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 provides Selenium commands for javascript-like conditionals, looping, callable functions, error catching, and JSON/XML driven parameterization. @@ -22,6 +22,8 @@ Features [Firefox Installer](https://addons.mozilla.org/en-US/firefox/addon/selenium-ide-sel-blocks/) / [Documentation](http://refactoror.wikia.com/wiki/Selblocks_Reference) +The Selenium server user-extensions.js file is in "/user extension/user-extensions.js". Grab a copy and follow the directions in the SeleniumHTMLRunner.cmd file. + Contributors 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. From 0b7d4e736129589ef8e094f167fe68d6a5608d6d Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 02:32:51 -0500 Subject: [PATCH 040/116] Adds readme about running the server tests --- testUserExtension/README.md | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 testUserExtension/README.md diff --git a/testUserExtension/README.md b/testUserExtension/README.md new file mode 100644 index 0000000..6222a42 --- /dev/null +++ b/testUserExtension/README.md @@ -0,0 +1,57 @@ +#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 +``` + +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. + +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. + +See also: http://selenium.googlecode.com/git-history/rc-0.9.2/website/tutorial.html \ No newline at end of file From 78842943a668ad77a641ad06973182cdfb27a746 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 02:49:22 -0500 Subject: [PATCH 041/116] updates testing readme --- testUserExtension/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testUserExtension/README.md b/testUserExtension/README.md index 6222a42..5d188f0 100644 --- a/testUserExtension/README.md +++ b/testUserExtension/README.md @@ -34,6 +34,9 @@ C:\projects | \---user extension | \---scripts +---server + chromedriver.exe + IEDriverServer.exe + selenium-server-standalone-2.43.1.jar ``` Then run `createSelbenchUserExtensions.cmd` From c445781c427f3876705f5ed810c12cb9f30955f2 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 04:57:19 -0500 Subject: [PATCH 042/116] updates test for error message in chrome & ie The error thrown has a little bit different message in IE and Google Chrome. This updates the test to reflect that. --- sel-blocksTests/branching.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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/ From 8aed50bdc4b19b61d8a0b75e382f2fc2e19aa13f Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 05:29:40 -0500 Subject: [PATCH 043/116] updates uneval to JSON.stringify for all browsers uneval only worked in firefox and it's not as great as JSON. This works in firefox, google chrome, and internet explorer. The forjson test passes in all of them now. --- .../chrome/content/extensions/selblocks.js | 10 +++++----- user extension/user-extensions.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index c7dc33d..d5eb8fb 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1680,7 +1680,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]); @@ -1729,10 +1729,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) { diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 41931a3..3300dea 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -2246,7 +2246,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]); @@ -2295,10 +2295,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) { From 60ac6a8df54108788596f4c2f57eb0e7fec07c1e Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 07:22:21 -0500 Subject: [PATCH 044/116] doesn't delete results when running "all" browsers --- testUserExtension/runTestsOnServer.cmd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index d4219b1..542ea23 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -328,11 +328,11 @@ EXIT /B %ERRORLEVEL% SET nolog=false ) - CALL :cleanupLogsAndResults - IF NOT %ERRORLEVEL% EQU 0 ( - ENDLOCAL - EXIT /B %ERRORLEVEL% - ) +REM CALL :cleanupLogsAndResults +REM IF NOT %ERRORLEVEL% EQU 0 ( +REM ENDLOCAL +REM EXIT /B %ERRORLEVEL% +REM ) CALL :generateTestingUserExtension IF NOT %ERRORLEVEL% EQU 0 ( From 4342ec3d785d3e4526561e88886839e758afb74b Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 07:22:53 -0500 Subject: [PATCH 045/116] checking in test results from all browsers --- testUserExtension/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/testUserExtension/.gitignore b/testUserExtension/.gitignore index 80bf25c..b4cf059 100644 --- a/testUserExtension/.gitignore +++ b/testUserExtension/.gitignore @@ -1,3 +1,2 @@ *Log* -results* user-extensions.js \ No newline at end of file From d9b5dad4f56d14f7b65e1a1e18f67a92f55fea83 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 07:23:17 -0500 Subject: [PATCH 046/116] checking in test results from all browsers --- testUserExtension/results-firefox.html | 6379 ++++++++++++++++++ testUserExtension/results-googlechrome.html | 6379 ++++++++++++++++++ testUserExtension/results-piiexplore.html | 6392 +++++++++++++++++++ 3 files changed, 19150 insertions(+) create mode 100644 testUserExtension/results-firefox.html create mode 100644 testUserExtension/results-googlechrome.html create mode 100644 testUserExtension/results-piiexplore.html diff --git a/testUserExtension/results-firefox.html b/testUserExtension/results-firefox.html new file mode 100644 index 0000000..0668218 --- /dev/null +++ b/testUserExtension/results-firefox.html @@ -0,0 +1,6379 @@ + +Test suite results + +

Test suite results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
result:failed
totalTime:33
numTestTotal:45
numTestPasses:44
numTestFailures:1
numCommandPasses:59
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
+ + +
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
functionsubBub
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 2~/])"
+ + +
 
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: 0"
+ + +
 
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 0"
+ + +
 
function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
subtest
resetEmitted
deleteVarssname, srole
emit"START ${sname} ${srole}"
calldoSomethingsname = "dilbert,Q", srole = "goof"
functiondoSomethingsname
emit"sname=${sname},srole=${srole}"
endFunctiondoSomething
calldoSomethingsname = "dogbert", srole = "woof"
calldoSomethingsname = "ratbert", srole = "squeak"
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
endForeach
emit"DONE ${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}"
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
resetEmitted
scriptdoDeprecatedsname
emit"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEmitted"sname=wally,srole=lazy"
+ + +
 
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
+ + +
 
+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]
+info: Executing: |function | subBub |  |
+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]
+info: Executing: |function | subBub |  |
+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]
+info: Executing: |function | subBub |  |
+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 |  |
+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 2~/])" |  |
+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: 0" |  |
+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.208 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 0" |  |
+info: Starting test /selenium-server/tests/function.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |emit | "START ${sname} ${srole}" |  |
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @4: [call|doSomething|sname = "dilbert,Q", srole = "goof"]
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: Executing: |function | doSomething | sname |
+info: [SelBlocks] branch => @7: [endFunction|doSomething]
+info: Executing: |endFunction | doSomething |  |
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @8: [call|doSomething|sname = "dogbert", srole = "woof"]
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @9: [call|doSomething|sname = "ratbert", srole = "squeak"]
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @10: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @10: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: [SelBlocks] branch => @12: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "DONE ${sname} ${srole}" |  |
+info: Executing: |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}" |  |
+info: Executing: |expectError | "Function does not exist: NONEXISTENT" |  |
+info: Executing: |call | NONEXISTENT |  |
+error: [SelBlocks] Error @16: [call|NONEXISTENT] Function does not exist: NONEXISTENT.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |resetEmitted |  |  |
+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 => @20: [endScript|doDeprecated]
+info: Executing: |endScript | doDeprecated |  |
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: [SelBlocks] branch => @18: [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: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endScript | doDeprecated |  |
+info: [SelBlocks] branch => @21: [call|doDeprecated|sname = "wally", srole = "lazy"]
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: Executing: |assertEmitted | "sname=wally,srole=lazy" |  |
+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.796 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
+
\ No newline at end of file diff --git a/testUserExtension/results-googlechrome.html b/testUserExtension/results-googlechrome.html new file mode 100644 index 0000000..bd1ba3d --- /dev/null +++ b/testUserExtension/results-googlechrome.html @@ -0,0 +1,6379 @@ + +Test suite results + +

Test suite results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
result:failed
totalTime:14
numTestTotal:45
numTestPasses:44
numTestFailures:1
numCommandPasses:59
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
+ + +
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
functionsubBub
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 2~/])"
+ + +
 
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: 0"
+ + +
 
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 0"
+ + +
 
function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
subtest
resetEmitted
deleteVarssname, srole
emit"START ${sname} ${srole}"
calldoSomethingsname = "dilbert,Q", srole = "goof"
functiondoSomethingsname
emit"sname=${sname},srole=${srole}"
endFunctiondoSomething
calldoSomethingsname = "dogbert", srole = "woof"
calldoSomethingsname = "ratbert", srole = "squeak"
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
endForeach
emit"DONE ${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}"
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
resetEmitted
scriptdoDeprecatedsname
emit"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEmitted"sname=wally,srole=lazy"
+ + +
 
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
+ + +
 
+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]
+info: Executing: |function | subBub |  |
+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]
+info: Executing: |function | subBub |  |
+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]
+info: Executing: |function | subBub |  |
+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 |  |
+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 2~/])" |  |
+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: 0" |  |
+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.675 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 0" |  |
+info: Starting test /selenium-server/tests/function.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |emit | "START ${sname} ${srole}" |  |
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @4: [call|doSomething|sname = "dilbert,Q", srole = "goof"]
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: Executing: |function | doSomething | sname |
+info: [SelBlocks] branch => @7: [endFunction|doSomething]
+info: Executing: |endFunction | doSomething |  |
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @8: [call|doSomething|sname = "dogbert", srole = "woof"]
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @9: [call|doSomething|sname = "ratbert", srole = "squeak"]
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @10: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @10: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: [SelBlocks] branch => @12: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "DONE ${sname} ${srole}" |  |
+info: Executing: |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}" |  |
+info: Executing: |expectError | "Function does not exist: NONEXISTENT" |  |
+info: Executing: |call | NONEXISTENT |  |
+error: [SelBlocks] Error @16: [call|NONEXISTENT] Function does not exist: NONEXISTENT.
+warn: [SelBlocks] __Stack Trace__
+info: Executing: |resetEmitted |  |  |
+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 => @20: [endScript|doDeprecated]
+info: Executing: |endScript | doDeprecated |  |
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: [SelBlocks] branch => @18: [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: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endScript | doDeprecated |  |
+info: [SelBlocks] branch => @21: [call|doDeprecated|sname = "wally", srole = "lazy"]
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: Executing: |assertEmitted | "sname=wally,srole=lazy" |  |
+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.253 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
+
\ No newline at end of file diff --git a/testUserExtension/results-piiexplore.html b/testUserExtension/results-piiexplore.html new file mode 100644 index 0000000..05bccb7 --- /dev/null +++ b/testUserExtension/results-piiexplore.html @@ -0,0 +1,6392 @@ + +Test suite results + +

Test suite results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
result:failed
totalTime:35
numTestTotal:45
numTestPasses:43
numTestFailures:2
numCommandPasses:59
numCommandFailures:0
numCommandErrors:2
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
+ + +
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
functionsubBub
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 2~/])"
+ + +
 
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: 0"
+ + +
 
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}"
foreachlinkCommand 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: Object doesn't support property or method 'evaluate'
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}"
+ + +
 
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 0"
+ + +
 
function.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
subtest
resetEmitted
deleteVarssname, srole
emit"START ${sname} ${srole}"
calldoSomethingsname = "dilbert,Q", srole = "goof"
functiondoSomethingsname
emit"sname=${sname},srole=${srole}"
endFunctiondoSomething
calldoSomethingsname = "dogbert", srole = "woof"
calldoSomethingsname = "ratbert", srole = "squeak"
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
endForeach
emit"DONE ${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}"
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
resetEmitted
scriptdoDeprecatedsname
emit"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEmitted"sname=wally,srole=lazy"
+ + +
 
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
+ + +
 
+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__
+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]
+info: Executing: |function | subBub |  |
+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]
+info: Executing: |function | subBub |  |
+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]
+info: Executing: |function | subBub |  |
+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 |  |
+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 2~/])" |  |
+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:1811: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:1045: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: 0" |  |
+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") |
+error: [SelBlocks] XPATH: //input
+error: [SelBlocks] Error  While evaluating Javascript expression: [$X("//input")]
+warn: [SelBlocks] __Stack Trace__
+error: Unexpected Exception: Object doesn't support property or method 'evaluate'
+error: Exception details: description -> Object doesn't support property or method 'evaluate', number -> -2146827850, stack -> TypeError: Object doesn't support property or method 'evaluate'
+   at $$.xp.evaluateXpath (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:800:9)
+   at $$.xp.selectNodes (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:841:7)
+   at $$.xp.selectElements (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:828:7)
+   at $X (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:1165:5)
+   at eval code (eval code:1:21)
+   at evalWithVars (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2482:7)
+   at Anonymous function (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2182:11)
+   at enterLoop (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2312:7)
+   at Selenium.prototype.doForeach (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2177:5)
+   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: Object doesn't support property or method 'evaluate'
+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.247 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 0" |  |
+info: Starting test /selenium-server/tests/function.html
+info: Executing: |resetEmitted |  |  |
+info: Executing: |deleteVars | sname, srole |  |
+info: Executing: |emit | "START ${sname} ${srole}" |  |
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @4: [call|doSomething|sname = "dilbert,Q", srole = "goof"]
+info: Executing: |call | doSomething | sname = "dilbert,Q", srole = "goof" |
+info: Executing: |function | doSomething | sname |
+info: [SelBlocks] branch => @7: [endFunction|doSomething]
+info: Executing: |endFunction | doSomething |  |
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @8: [call|doSomething|sname = "dogbert", srole = "woof"]
+info: Executing: |call | doSomething | sname = "dogbert", srole = "woof" |
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @9: [call|doSomething|sname = "ratbert", srole = "squeak"]
+info: Executing: |call | doSomething | sname = "ratbert", srole = "squeak" |
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @10: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: [SelBlocks] branch => @5: [function|doSomething|sname]
+info: Executing: |function | doSomething | sname |
+info: Executing: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endFunction | doSomething |  |
+info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"]
+info: Executing: |call | doSomething | sname = sname, srole = "super=user" |
+info: Executing: |endForeach |  |  |
+info: [SelBlocks] branch => @10: [foreach|sname|"asok", "alice"]
+info: Executing: |foreach | sname | "asok", "alice" |
+info: [SelBlocks] branch => @12: [endForeach]
+info: Executing: |endForeach |  |  |
+info: Executing: |emit | "DONE ${sname} ${srole}" |  |
+info: Executing: |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}" |  |
+info: Executing: |expectError | "Function does not exist: NONEXISTENT" |  |
+info: Executing: |call | NONEXISTENT |  |
+error: [SelBlocks] Error @16: [call|NONEXISTENT] Function does not exist: NONEXISTENT.
+warn: [SelBlocks] __Stack Trace__
+warn: [SelBlocks] @@ No stack trace, (Firefox only)
+info: Executing: |resetEmitted |  |  |
+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 => @20: [endScript|doDeprecated]
+info: Executing: |endScript | doDeprecated |  |
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: [SelBlocks] branch => @18: [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: |emit | "sname=${sname},srole=${srole}" |  |
+info: Executing: |endScript | doDeprecated |  |
+info: [SelBlocks] branch => @21: [call|doDeprecated|sname = "wally", srole = "lazy"]
+info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" |
+info: Executing: |assertEmitted | "sname=wally,srole=lazy" |  |
+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.221 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
+
\ No newline at end of file From bed9bc463c5ef9dbdb90f68ecabec226e42aa35c Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 19:12:34 -0500 Subject: [PATCH 047/116] Refactors "evlauateXpath" to work everywhere I hooked into the library selenium uses, which are inherited from the browserbot. There are five or so by default, and the user can switch them somehow... so I didn't dig too deep. I just assumed they'd all provide an "evaluate" method and went from there. --- .../content/extensions/xpath-processing.js | 55 ++++++++++++++++--- user extension/user-extensions.js | 55 ++++++++++++++++--- 2 files changed, 92 insertions(+), 18 deletions(-) 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/user extension/user-extensions.js b/user extension/user-extensions.js index 3300dea..dbab547 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -267,19 +267,56 @@ globalContext = this; $$.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); } @@ -288,9 +325,9 @@ globalContext = this; //$$.LOG.traceback(err); throw err; } - if (isResultObjProvided) + if (isResultObjProvided) { result = resultObj; - + } return result; } From 4584ccd3670c1a9f288cfee963bca880a8aa3a2d Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 19:26:27 -0500 Subject: [PATCH 048/116] All tests pass in all server environments and IDE. --- IDE test results.html | 4197 +++++++++++++++++++ testUserExtension/results-firefox.html | 6 +- testUserExtension/results-googlechrome.html | 6 +- testUserExtension/results-piiexplore.html | 73 +- 4 files changed, 4241 insertions(+), 41 deletions(-) create mode 100644 IDE test results.html diff --git a/IDE test results.html b/IDE test results.html new file mode 100644 index 0000000..3624ee9 --- /dev/null +++ b/IDE test results.html @@ -0,0 +1,4197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test Suite Results
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
+ + + + + + + +
README
openhttp://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
functionsubBub
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
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
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
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
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
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
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
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 2~/])"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
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"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
while
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: 0"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
for
resetEmitted
deleteVarsf
emit"START ${f}"
fors=0,f=3; f <= 5; f++
emit"iter=${f}.${s}"
endFor
emit"END ${f}"
assertEmitted"START ${commands}quot; + "{f}~iter=3.0~iter=4.0~iter=5.0~END ${commands}quot; + "{f}"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
foreach
resetEmitted
deleteVars_i, fe
emit"START ${_i}-${fe}"
foreachfe"dilbert", "dogbert", "wally"
emit"${_i}) ${fe}"
endForeach
emit"END ${_i}-${fe}"
assertEmitted"START ${commands}quot; + "{_i}-${commands}quot; + "{fe}~0) dilbert~1) dogbert~2) wally~END ${commands}quot; + "{_i}-${commands}quot; + "{fe}"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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}"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
forjson
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 ${commands}quot; + "{jname}~dilbert~dogbert~wally~INTERMISSION ${commands}quot; + "{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
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 ${commands}quot; + "{xname}~dilbert~dogbert~wally~INTERMISSION ${commands}quot; + "{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
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
resetEmitted
store0i
whilei++ < 10
continuei==3
breaki==5
emit"iter=${i}"
endWhile
assertEmitted"iter=1~iter=2~iter=4"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
continue-break 3
resetEmitted
foreachfe"dilbert","dogbert","wally"
continuefe=="dogbert"
breakfe=="wally"
emit"iter=${fe}"
endForeach
assertEmitted"iter=dilbert"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
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 0"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
function
resetEmitted
deleteVarssname, srole
emit"START ${sname} ${srole}"
calldoSomethingsname = "dilbert,Q", srole = "goof"
functiondoSomethingsname
emit"sname=${sname},srole=${srole}"
endFunctiondoSomething
calldoSomethingsname = "dogbert", srole = "woof"
calldoSomethingsname = "ratbert", srole = "squeak"
foreachsname"asok", "alice"
calldoSomethingsname = sname, srole = "super=user"
endForeach
emit"DONE ${sname} ${srole}"
assertEmitted"START ${commands}quot; + "{sname} ${commands}quot; + "{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 ${commands}quot; + "{sname} ${commands}quot; + "{srole}"
expectError"Function does not exist: NONEXISTENT"
callNONEXISTENT
resetEmitted
scriptdoDeprecatedsname
emit"sname=${sname},srole=${srole}"
endScriptdoDeprecated
calldoDeprecatedsname = "wally", srole = "lazy"
assertEmitted"sname=wally,srole=lazy"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
function-recursive
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
functionxyz
log'here'
endFunction
callxyz
+
+ + + + + + + + + + + + + + + +
exitTest - base case
resetEmitted
exitTest
throw"shouldn't happen"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
calldoSubExit
throw"shouldn't happen"
functiondoSubExit
exitTest
endFunctiondoSubExit
+ + diff --git a/testUserExtension/results-firefox.html b/testUserExtension/results-firefox.html index 0668218..b4a960e 100644 --- a/testUserExtension/results-firefox.html +++ b/testUserExtension/results-firefox.html @@ -54,7 +54,7 @@

Test suite results

totalTime: -33 +37 numTestTotal: @@ -6107,7 +6107,7 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 2.208 sec elapsed: +info: [SelBench] 2.205 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 0" | | info: Starting test /selenium-server/tests/function.html info: Executing: |resetEmitted | | | @@ -6253,7 +6253,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.796 sec elapsed: factorial 7 +info: [SelBench] 0.814 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] diff --git a/testUserExtension/results-googlechrome.html b/testUserExtension/results-googlechrome.html index bd1ba3d..e5a8825 100644 --- a/testUserExtension/results-googlechrome.html +++ b/testUserExtension/results-googlechrome.html @@ -54,7 +54,7 @@

Test suite results

totalTime: -14 +12 numTestTotal: @@ -6107,7 +6107,7 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 0.675 sec elapsed: +info: [SelBench] 0.804 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 0" | | info: Starting test /selenium-server/tests/function.html info: Executing: |resetEmitted | | | @@ -6253,7 +6253,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.253 sec elapsed: factorial 7 +info: [SelBench] 0.292 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] diff --git a/testUserExtension/results-piiexplore.html b/testUserExtension/results-piiexplore.html index 05bccb7..4bf8a1f 100644 --- a/testUserExtension/results-piiexplore.html +++ b/testUserExtension/results-piiexplore.html @@ -54,7 +54,7 @@

Test suite results

totalTime: -35 +31 numTestTotal: @@ -62,11 +62,11 @@

Test suite results

numTestPasses: -43 +44 numTestFailures: -2 +1 numCommandPasses: @@ -78,7 +78,7 @@

Test suite results

numCommandErrors: -2 +1 Selenium Version: @@ -91,7 +91,7 @@

Test suite results

- + @@ -123,7 +123,7 @@

Test suite results

- + @@ -3565,7 +3565,7 @@

Test suite results

+
Test Suite
Test Suite
README
eval
branching
while
for
foreach
foreach-xpath
foreach-xpath
forjson
forxml
continue-break 1
foreach-xpath.html
- + @@ -3592,32 +3592,32 @@

Test suite results

- + - + - + - + - + - + - + - + @@ -5623,11 +5623,11 @@

Test suite results

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:1811:5) + at Selenium.prototype.doThrow (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:1848: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:1045:7) + at $$.handleAsTryBlock (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:1082: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 @@ -5710,22 +5710,25 @@

Test suite results

info: Executing: |echo | begin | | info: Executing: |emit | "START ${_i}) ${link}" | | info: Executing: |foreach | link | $X("//input") | -error: [SelBlocks] XPATH: //input -error: [SelBlocks] Error While evaluating Javascript expression: [$X("//input")] -warn: [SelBlocks] __Stack Trace__ -error: Unexpected Exception: Object doesn't support property or method 'evaluate' -error: Exception details: description -> Object doesn't support property or method 'evaluate', number -> -2146827850, stack -> TypeError: Object doesn't support property or method 'evaluate' - at $$.xp.evaluateXpath (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:800:9) - at $$.xp.selectNodes (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:841:7) - at $$.xp.selectElements (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:828:7) - at $X (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:1165:5) - at eval code (eval code:1:21) - at evalWithVars (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2482:7) - at Anonymous function (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2182:11) - at enterLoop (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2312:7) - at Selenium.prototype.doForeach (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2177:5) - 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: Object doesn't support property or method 'evaluate' +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 | @@ -6119,7 +6122,7 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 3.247 sec elapsed: +info: [SelBench] 3.211 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 0" | | info: Starting test /selenium-server/tests/function.html info: Executing: |resetEmitted | | | @@ -6266,7 +6269,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 1.221 sec elapsed: factorial 7 +info: [SelBench] 1.181 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] From 9b8942da03dc943711490f687143210bb8f54065 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 21:12:52 -0500 Subject: [PATCH 049/116] updates docs on running tests --- testUserExtension/README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/testUserExtension/README.md b/testUserExtension/README.md index 5d188f0..ebd498b 100644 --- a/testUserExtension/README.md +++ b/testUserExtension/README.md @@ -43,7 +43,7 @@ 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. + to launch the automatic tests in firefox. 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 @@ -57,4 +57,15 @@ As soon as the automatic tests complete, the results should open in your 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 \ No newline at end of file From 057179e72c3f6dafe1034bfd3575f2a60a1bb904 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 21:14:12 -0500 Subject: [PATCH 050/116] adds reg files to enable and disable proxy for IE You have to open IE after applying these registry changes. It won't change the settings while IE is running. --- .../Proxy localhost 4444 disable.reg | Bin 0 -> 584 bytes testUserExtension/Proxy localhost 4444 enable.reg | Bin 0 -> 584 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 testUserExtension/Proxy localhost 4444 disable.reg create mode 100644 testUserExtension/Proxy localhost 4444 enable.reg diff --git a/testUserExtension/Proxy localhost 4444 disable.reg b/testUserExtension/Proxy localhost 4444 disable.reg new file mode 100644 index 0000000000000000000000000000000000000000..720013d3903408674c852587770a8e160b9202f4 GIT binary patch literal 584 zcmaix?MlNi6o%j51Mgwv0>py;87jyaO#GyC%CI8U)me~4(rWeQ)hB7i4nYaY`F_uN zPd-1cRLW{8r$&{AN>yluuTm|qcRUlKC6>b;>XNu8T4G!59c^lhv!Ow}*P7~xnuTsP z)*QSP>r@xmbIs6GWk{z7FdOBd6?jfSyhnFnx3Ns?vt{7DkP-4Nwd<2)I*i^hoh74Y zwpo-l$QDkOZsLR{_F9pblU3*(&FKxUMtg8=usm`Uc?E9mNxJHv{0X?Z?(_u8-?i<2 zOt06J-nE{Uu)pM=>hI16@DKkm=34ew!YXX|IMy59@C*GeVFO;T@eLCiW_9d2M?Rv3 aUmj_@JHPACx>`@KWyjKJw}-M1=0IQW2w@cf literal 0 HcmV?d00001 diff --git a/testUserExtension/Proxy localhost 4444 enable.reg b/testUserExtension/Proxy localhost 4444 enable.reg new file mode 100644 index 0000000000000000000000000000000000000000..07207aeb54212a9b3c48c4b21bfc233607335279 GIT binary patch literal 584 zcmb7>-AV&75QWcm!FMQm0C7QYiWa04D*m#y6>&>h?OGQkk?iW~%iDfQ7i{rH3CYZ4 z=A6u#tiJD5%4#8}MwPlsRcOgwrCMHJ+ziQm$ zmWrC*#?jU=TQpUg#STq;Ye`*BRiPU^r%$vRouIWL^4MO~6|`+u(xQLrhw$cl)GI9i z#g2Hp)|(RMm;4cZivI8q1GZ&;C91-NFCyM>hF>sSioyiEKH?cVH1z72bB=w%3%}gc XVY`0guUo9=twpQS=y;2z4`)Yf?&x6_ literal 0 HcmV?d00001 From 4779fa1bd7625edb77c004597ac099cbe19989e3 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 23:21:58 -0500 Subject: [PATCH 051/116] Error: infinite loop calling func from another case An error is thrown when calling a function that hasn't been defined in the suite. If the function was defined in the same test case then it will run. If the function was defined in another test case, it looks like the index range is remembered but the commands are taken from the current test case. When those commands execute successfully, infinite recursion occurs. It looks like functions are almost global. They should be, it would be much more useful to define all the functions in one "case" that could be used like a library, then call those functions in cases that come after the library case(s) was/were loaded. --- sel-blocksTests/CallGlobalFunction.html | 41 ++++++++++++++ sel-blocksTests/CreateGlobalVars.html | 22 ++++++++ sel-blocksTests/GlobalFunctions.html | 56 +++++++++++++++++++ sel-blocksTests/GlobalFunctionsTestSuite.html | 16 ++++++ 4 files changed, 135 insertions(+) create mode 100644 sel-blocksTests/CallGlobalFunction.html create mode 100644 sel-blocksTests/CreateGlobalVars.html create mode 100644 sel-blocksTests/GlobalFunctions.html create mode 100644 sel-blocksTests/GlobalFunctionsTestSuite.html diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html new file mode 100644 index 0000000..0410cb4 --- /dev/null +++ b/sel-blocksTests/CallGlobalFunction.html @@ -0,0 +1,41 @@ + + + + + + +CallGlobalFunction + + +
foreachX
foreachX
resetEmitted "START ${_i}) ${link}"
foreach linkCommand 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: Object doesn't support property or method 'evaluate'$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}"
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + diff --git a/sel-blocksTests/CreateGlobalVars.html b/sel-blocksTests/CreateGlobalVars.html new file mode 100644 index 0000000..942bab6 --- /dev/null +++ b/sel-blocksTests/CreateGlobalVars.html @@ -0,0 +1,22 @@ + + + + + + +CreateGlobalVars + + + + + + + + + + + + +
CreateGlobalVars
getEvalglobalStoredVars = {};
+ + diff --git a/sel-blocksTests/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html new file mode 100644 index 0000000..d17e662 --- /dev/null +++ b/sel-blocksTests/GlobalFunctions.html @@ -0,0 +1,56 @@ + + + + + + +functions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
functions
functionsetGlobalVar
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html new file mode 100644 index 0000000..e088f8e --- /dev/null +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -0,0 +1,16 @@ + + + + + + Test Suite + + + + + + + +
Test Suite
CreateGlobalVars
GlobalFunctions
CallGlobalFunction
+ + From 5c0815a3525918ecca65317ec548473964115b72 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 30 Dec 2014 23:33:03 -0500 Subject: [PATCH 052/116] removes unnecessary base url from test cases I forgot to turn off the option to remember base urls. --- sel-blocksTests/CallGlobalFunction.html | 1 - sel-blocksTests/CreateGlobalVars.html | 1 - sel-blocksTests/GlobalFunctions.html | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html index 0410cb4..a511df7 100644 --- a/sel-blocksTests/CallGlobalFunction.html +++ b/sel-blocksTests/CallGlobalFunction.html @@ -3,7 +3,6 @@ - CallGlobalFunction diff --git a/sel-blocksTests/CreateGlobalVars.html b/sel-blocksTests/CreateGlobalVars.html index 942bab6..969fed7 100644 --- a/sel-blocksTests/CreateGlobalVars.html +++ b/sel-blocksTests/CreateGlobalVars.html @@ -3,7 +3,6 @@ - CreateGlobalVars diff --git a/sel-blocksTests/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html index d17e662..da38020 100644 --- a/sel-blocksTests/GlobalFunctions.html +++ b/sel-blocksTests/GlobalFunctions.html @@ -3,8 +3,7 @@ - -functions +GlobalFunctions From 1b2acc6631b2747f446c4a1ae566c3470e6855d9 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Wed, 31 Dec 2014 21:43:09 -0500 Subject: [PATCH 053/116] draft to add global functions This doesn't really work yet. It looks like it works sometimes but it's really not. --- .../chrome/content/extensions/selblocks.js | 730 +++++++++++++----- 1 file changed, 521 insertions(+), 209 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index f6ba739..71793e4 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -123,19 +123,18 @@ function $X(xpath, contextNode, resultType) { // 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) - { + 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 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); + if (c === t1.substr(t, 1)) { + c = t2.substr(t, 1); break; } } @@ -150,39 +149,225 @@ function $X(xpath, contextNode, resultType) { return t2[i]; } } - } - else { + } else { assert(false, "translate() function requires arguments of type String or Array"); } return null; }; + // ----- SelBlocksGlobal: + /** @param TestCase optional + * @return int 0-based index of given test case within the list of test cases + * of the test suite + **/ + function testCaseIdx(givenTestCase) { + var msg, + caseIndex; + givenTestCase = givenTestCase || testCase; + // Must not use assert() here, because that calls notifyFatalHere() which calls idxHere() + // which calls globIdx() which calls testCaseIdx() + if (typeof givenTestCase !== 'object') { + msg = "SelBlocks error: in testCaseIdx(), param givenTestCase is not an object, neither global testCase is."; + LOG.error(msg); + throw new Error(msg); + } + if (editor.app.testSuite.tests.length === 0) { + msg = "SelBlocks error: in testCaseIdx(), bad editor.app.testSuite.tests.length===0."; + LOG.error(msg); + throw new Error(msg); + } + for (caseIndex = editor.app.testSuite.tests.length - 1; caseIndex >= 0; caseIndex--) { + if (editor.app.testSuite.tests[caseIndex].content === givenTestCase) { + break; + } + } + if (caseIndex < 0) { + msg = "SelBlocks error: in testCaseIdx(), givenTestCase was not matched."; + LOG.error(msg); + throw new Error(msg); + } + return caseIndex; + } + + function logAndThrow(msg) { + var error = new Error(msg); + LOG.error(msg + "\n" + error.stack); + throw error; + } + /** This serves to generate unique global identifiers for test script commands. + * Results of this functions are usually values of symbols[] and other structures. + * @param {number} commandIndex 0-based index within givenTestCase (or within testCase). + * @param {TestCase} [givenTestCase] optional; using (current) testCase by default + // I'd rather use objects, but Javascript doesn't compare objects field by field + // - try javascript:a={first: 1}; b={first: 1}; a==b + @returns {string} global index of the command, in form testCaseIndex/commandIndex + */ + function globIdx(commandIndex, givenTestCase) { + givenTestCase = givenTestCase || testCase; + // Must not use assert() here, because that calls notifyFatalHere() which calls idxHere() which calls globIdx() + if (typeof commandIndex !== 'number' || commandIndex < 0) { + logAndThrow("SelBlocks error: in globIdx(), bad type/value of the first parameter commandIndex: " + commandIndex); + } + if (typeof givenTestCase !== 'object') { + logAndThrow("SelBlocks error: in globIdx(), bad type of the optional second parameter givenTestCase (or global testCase)."); + } + var caseIndex = testCaseIdx(givenTestCase); + return '' + caseIndex + '/' + commandIndex; + } + /** @return {number} (not a Number object) 0-based index of the respective command within its test case + * @param {string} globIdxValue Global index of a test command (test step). + */ + function localIdx(globIdxValue) { + var msg, + lastSlashIndex; + // Can't use assert() here, since assert indirectly calls fmtCmdRef() which calls localIdx() - recursion + if (typeof globIdxValue !== 'string') { + msg = 'globIdxValue must be a string, but got ' + (typeof globIdxValue) + ': ' + globIdxValue; + LOG.error(msg); + throw new Error(msg); + } + lastSlashIndex = globIdxValue.lastIndexOf('/'); + if (lastSlashIndex <= 0) { + msg = 'globIdxValue must contain "/" and not as the first character.'; + LOG.error(msg); + throw new Error(msg); + } + if (lastSlashIndex >= globIdxValue.length) { + msg = 'globIdxValue must contain "/" and not as the last character.'; + LOG.error(msg); + throw new Error(msg); + } + var afterSlash = globIdxValue.substr(lastSlashIndex + 1); + var afterSlashNumber = Number(afterSlash); + if (afterSlash !== '' + afterSlashNumber) { + msg = 'The part after "/" must be numeric.'; + LOG.error(msg); + throw new Error(msg); + } + var result = afterSlashNumber.valueOf(); + //"TODO:" + if (result < 0 || result >= editor.app.testSuite.tests[localCaseIdxPart(globIdxValue)].content.commands.length) { + msg = 'In localIdx("' + globIdxValue + '"), result ' + result + ' is not a valid command index'; + LOG.error(msg); + throw new Error(msg); + } + return result; + } + /**@param string result of globIdx() or of labelIdx() + * @return {number} (not a Number object) 0-based index of the test case (for the given global index) + * within the list of test cases (i.e. editor.app.testSuite.tests) + */ + function localCaseIdxPart(globIdxValue) { + assert(typeof globIdxValue === 'string', 'globIdxValue must be a string.'); + var lastSlashIndex = globIdxValue.lastIndexOf('/'); + assert(lastSlashIndex > 0, 'globIdxValue must contain "/" and not as the first character.'); + assert(lastSlashIndex < globIdxValue.length - 1, 'globIdxValue must contain "/" and not as the last character.'); + var beforeSlash = globIdxValue.substring(0, globIdxValue.lastIndexOf('/')); + var beforeSlashNumber = Number(beforeSlash); + assert('' + beforeSlash === '' + beforeSlashNumber, 'The part after "/" must be numeric.'); + var result = beforeSlashNumber.valueOf(); + assert(result >= 0 && result < editor.app.testSuite.tests.length, 'result not a valid index into editor.app.testSuite.tests.'); + return result; + } + /** global array of _usable_ test cases, set in compileSelBlocks(). + * It contains test cases in the same order as in editor.app.testSuite.tests[], + * but here they are as they come from editor.getTestCase() + **/ + var testCases = []; + + // @return TestCase test case for the given global index + function localCase(globIdxValue) { + var index = localCaseIdxPart(globIdxValue); + assert(index < testCases.length, 'case index: ' + index + ' but testCases[] has length ' + testCases.length); + return testCases[index]; + /* Following didn't work: + return editor.app.testSuite.tests[ localCaseIdxPart(globIdxValue) ].content; + */ + } + /** @return {Object} Command structure for given global index + * */ + function localCommand(globIdxValue) { + return localCase(globIdxValue).commands[localIdx(globIdxValue)]; + } + + /** This serves to generate and compare keys in symbols[] for label commands + * @param string label name + * @param TestCase test case where the label is; optional - using testCase by default + * @return string global label identifier in form 'test-case-index/label' + **/ + function labelIdx(label, givenTestCase) { + assert(typeof label === 'string', 'label must be a string.'); + givenTestCase = givenTestCase || testCase; + return '' + testCaseIdx(givenTestCase) + '/' + label; + } + // @TODO on insert, validate that function names are unique, i.e. no function overriding //=============== 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 object symbols */ + var symbols = {}; // command indexes stored by name: function names + /** @var {BlockDefs} Static command definitions stored by command index. Global, used for all test cases. */ + var blockDefs = null; // static command definitions stored by command index + /** @var {Stack} callStack Command execution stack */ + var callStack = null; // command execution stack // the idx of the currently executing command - function idxHere() { - return testCase.debugContext.debugIndex; + // SelBlocksGlobal added param relativeShift and made it return a global, cross-test case index, rather than local (test-case specific) index + /** @param {number} [relativeShift=0] Relative shift to the current command's position + * @return {string} global command index + * */ + function idxHere(relativeShift) { + // Must not use assert() here, because that calls notifyFatalHere() which calls idxHere() + return globIdx(localIdxHere(relativeShift)); + } + /** @param {number} [relativeShift=0] Relative shift to the current command's position + * @return {number} Current command's position (within current test case), adjusted by relativeShift. Depending on relativeShift the result may not be a valid position. + * */ + function localIdxHere(relativeShift) { + relativeShift = relativeShift || 0; + return testCase.debugContext.debugIndex + relativeShift; } // Command structure definitions, stored by command index + // SelBlocksGlobal: stored by command global index - i.e. value of idxHere() function BlockDefs() { - var blkDefs = []; - // initialize blockDef at the given command index - blkDefs.init = function(i, attrs) { + //@TODO use this.xxx=yyy, and define init() on BlockDefs.prototype. Then NetBeans navigation is easier. + /** @var {object} Serving as an associative array {globIdx => object of {any attributes, idx, cmdName}}. SelBlocksGlobal changed this from an array to an object. */ + var blkDefs = {}; + // initialize an entry in BlockDefs instance at the given command global index + /** @param {string} i Global index, a result of globIdx() function + * @param {Object} [attrs] Extra details to add, depending on the command: + * nature: 'if', 'try', 'loop', 'function' + * elseIfIdxs - array, used for 'if' + * ifIdx - used for 'else', 'elseIf' and 'endIf'; it's a global index of the matching 'if' step + * name - used for 'try', it's 'target' of the step (the 2nd column in Selenium IDE) + * tryIdx - used by 'catch', 'finally' and 'endTry', index of the matching 'try' + * finallyIdx + * beginIdx - used by 'continue', 'break', endWhile, endFor, endForeach, endForJson, endForXml; + * it's an index of the start of the current loop + * endIdx + * funcIdx - used by 'return', 'endfunction', 'endScript' + * @TODO check beginIdx and other fields - set after calls to blkDefFor(), blkDefAt() + * @return {object} A new entry just added to this collection. + * @see variable blkDefs + **/ + blkDefs.init = function BlockDefsInit(i, attrs) { + assert(typeof testCase.commands === 'object', 'BlockDefs::init() - testCase.commands is of bad type.'); + // @TODO assert regex numeric/numeric + assert(typeof i === 'string', 'BlockDefs::init() - param i must be a globIdx() result.'); + // @TODO change to use 'this' instead of 'blkDefs' - it will be clearer. blkDefs[i] = attrs || {}; blkDefs[i].idx = i; - blkDefs[i].cmdName = testCase.commands[i].command; + // Following line is from original SelBlocks, here just for documentation + //blkDefs[i].cmdName = testCase.commands[i].command; + blkDefs[i].cmdName = localCase(i).commands[localIdx(i)].command; return blkDefs[i]; }; return blkDefs; } // retrieve the blockDef at the given command idx + /** @param {string} idx Global index of a test step. */ function blkDefAt(idx) { return blockDefs[idx]; } @@ -201,18 +386,24 @@ function $X(xpath, contextNode, resultType) { // 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 + stack.isEmpty = function isEmpty() { + return stack.length === 0; + }; + stack.top = function top() { + return stack[stack.length - 1]; + }; + stack.findEnclosing = function findEnclosing(_hasCriteria) { + return stack[stack.indexWhere(_hasCriteria)]; + }; + stack.indexWhere = function indexWhere(_hasCriteria) { // undefined if not found var i; - for (i = stack.length-1; i >= 0; i--) { + for (i = stack.length - 1; i >= 0; i--) { if (_hasCriteria(stack[i])) { return i; } } }; - stack.unwindTo = function(_hasCriteria) { + stack.unwindTo = function unwindTo(_hasCriteria) { if (stack.length === 0) { return null; } @@ -221,23 +412,35 @@ function $X(xpath, contextNode, resultType) { } return stack.top(); }; - stack.isHere = function() { + stack.isHere = function isHere() { 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"); }; - + 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 + // SelBLocksGlobal: This is a global index of the next command - set to a result of globIdx() var branchIdx = null; // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) + // See Selenium's {a6fd85ed-e919-4a43-a5af-8da18bda539f}/chrome/content/testCase.js + // This is for a head-intercept of TestCaseDebugContext.prototype.nextCommand(), and it adds support for SelBlocksGlobal branches (across test cases). + // We can't redefine/tail-intercept testCase.debugContext.nextCommand() at the time + // this SelBlocksGlobal source file is loaded, because testCase is not defined yet. Therefore we do it here + // on the first run of the enclosing tail intercept of Selenium.prototype.reset() below. + // And we intercept do it on the prototype, so that it applies to any test cases. function nextCommand() { if (!this.started) { this.started = true; @@ -246,11 +449,14 @@ function $X(xpath, contextNode, resultType) { else { if (branchIdx !== null) { $$.LOG.info("branch => " + fmtCmdRef(branchIdx)); - this.debugIndex = branchIdx; + this.debugIndex = localIdx(branchIdx); + + testCase= this.testCase= localCase(branchIdx); + testCase.debugContext= this; branchIdx = null; } else { - this.debugIndex++; + this.debugIndex++; // global removed this } } // skip over comments @@ -263,12 +469,17 @@ function $X(xpath, contextNode, resultType) { } return null; } + /** @param {string} globIdx value */ function setNextCommand(cmdIdx) { - assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, - " Cannot branch to non-existent command @" + (cmdIdx+1)); + var idx= localIdx(cmdIdx); + var localTestCase= localCase(cmdIdx); + assert( idx>=0 && idx< localTestCase.commands.length, + " Cannot branch to non-existent command @" +cmdIdx ); branchIdx = cmdIdx; } +(function () { // wrapper makes testCaseDebugContextWasIntercepted private + var testCaseDebugContextWasIntercepted; // undefined or true // Selenium calls reset(): // * before each single (double-click) command execution // * before a testcase is run @@ -287,37 +498,98 @@ function $X(xpath, contextNode, resultType) { 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); + + //if( testCaseDebugContextWasIntercepted===undefined ) { + // // SelBlocksGlobal: This is a head-intercept, rather than interceptReplace as in SelBlocks 2.0.1, + // // and I'm intercepting TestCaseDebugContext.prototype.nextCommand() rather than testCase.debugContext.nextCommand() + // $$.LOG.debug("Configuring head intercept: TestCaseDebugContext.prototype.nextCommand()"); + // $$.fn.interceptBefore(TestCaseDebugContext.prototype, "nextCommand", nextCommand); + // + // testCaseDebugContextWasIntercepted= true; + //} }); +}()); // get the blockStack for the currently active callStack function activeBlockStack() { return callStack.top().blockStack; } - // ================================================================================ // Assemble block relationships and symbol locations function compileSelBlocks() { + symbols= {}; // Let's clear symbols + // Currently, this is called multiple times when Se IDE runs the whole test suite + // - once per each test case. No harm in that, only a bit of wasted CPU. + + //alert( 'testCase===editor.suiteTreeView.getCurrentTestCase(): ' +(testCase===editor.suiteTreeView.getCurrentTestCase()) ); // --> false! + //alert( 'testCase===editor.getTestCase(): ' +(testCase===editor.getTestCase()) ); //--> true! + var testCaseOriginal= testCase; + testCaseOriginal= editor.getTestCase(); + var testCaseOriginalIndex= -1; + testCases= []; + //alert( 'editor.app.getTestSuite()===editor.app.testSuite: ' +editor.app.getTestSuite()===editor.app.testSuite ); // => false + //alert( 'editor.app.testSuite.tests.indexOf( testCase): ' +editor.app.testSuite.tests.indexOf( testCase) ); // => -1 + // SelBlocksGlobal: I set blockDefs before looping through test cases, because it's global - for all test cases blockDefs = new BlockDefs(); + for( var testCaseIndex=0; testCaseIndex=0, "testCaseOriginalIndex mut be non-negative!"); + // In the following, do not pass testCases[testCaseOriginalIndex]. + // is not the same as editor.app.getTestSuite().tests[testCaseOriginalIndex], because + // Application.prototype.showTestCaseFromSuite(givenTestCase) calls this.setTestCase(givenTestCase.content) + editor.app.showTestCaseFromSuite( editor.app.getTestSuite().tests[testCaseOriginalIndex] ); + testCase.debugContext.testCase= testCase; + } + // end of compileSelBlocks() + // SelBlocksGlobal: Following three functions were inside compileSelBlocksTestCase(), but that doesn't follow JS strict mode. Two of them didn't have to be closures. assertBlockIsPending() used to be a closure, now it received parameter lexStack and is not a closure anymore. + //- command validation + function assertNotAndWaitSuffix(cmdIdx) { + assertCmd(cmdIdx, localCase(cmdIdx).commands[ localIdx(cmdIdx) ].command.indexOf("AndWait") === -1, + ", AndWait suffix is not valid for SelBlocks commands"); + } + //- active block validation + function assertBlockIsPending(lexStack, 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)); + } + // SelBlocksGlobal factored the following out of SelBlocks' compileSelBlocks(), to make 'testCase' not refer + // to global testCase + function compileSelBlocksTestCase( testCase ) { + // SelBlocksGlobal: I set lexStack here, since it's local stack per testCase (and only used during compilation) var lexStack = new Stack(); - var i; - for (i = 0; i < testCase.commands.length; i++) + // SelBlocksGlobal: Following loop variable commandIndex was renamed from 'i' in SelBlocks. + // I set variable 'i' to globIdx() value of commandIndex (i.e. of the original intended value of 'i'). This way + // the original SelBlocks code still uses variable 'i', so there are less merge conflicts. + var commandIndex, i; + for (commandIndex = 0; commandIndex < testCase.commands.length; commandIndex++) { - if (testCase.commands[i].type === "command") + if (testCase.commands[commandIndex].type === "command") { - var curCmd = testCase.commands[i].command; + var curCmd = testCase.commands[commandIndex].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 cmdTarget = testCase.commands[commandIndex].target; + i= globIdx(commandIndex, testCase); var ifDef; var tryDef; var expectedCmd; @@ -325,7 +597,7 @@ function $X(xpath, contextNode, resultType) { { case "label": assertNotAndWaitSuffix(i); - symbols[cmdTarget] = i; + symbols[ labelIdx(cmdTarget, testCase) ] = i; break; case "goto": case "gotoIf": case "skipNext": assertNotAndWaitSuffix(i); @@ -337,7 +609,7 @@ function $X(xpath, contextNode, resultType) { break; case "elseIf": assertNotAndWaitSuffix(i); - assertBlockIsPending("elseIf", i, ", is not valid outside of an if/endIf block"); + assertBlockIsPending(lexStack, "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; @@ -349,7 +621,7 @@ function $X(xpath, contextNode, resultType) { break; case "else": assertNotAndWaitSuffix(i); - assertBlockIsPending("if", i, ", is not valid outside of an if/endIf block"); + assertBlockIsPending(lexStack, "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) { @@ -360,7 +632,7 @@ function $X(xpath, contextNode, resultType) { break; case "endIf": assertNotAndWaitSuffix(i); - assertBlockIsPending("if", i); + assertBlockIsPending(lexStack, "if", i); ifDef = lexStack.pop(); assertMatching(ifDef.cmdName, "if", i, ifDef.idx); blockDefs.init(i, { ifIdx: ifDef.idx }); // endIf -> if @@ -376,7 +648,7 @@ function $X(xpath, contextNode, resultType) { break; case "catch": assertNotAndWaitSuffix(i); - assertBlockIsPending("try", i, ", is not valid without a try block"); + assertBlockIsPending(lexStack, "try", i, ", is not valid without a try block"); tryDef = lexStack.top(); assertMatching(tryDef.cmdName, "try", i, tryDef.idx); if (blkDefFor(tryDef).catchIdx) { @@ -391,7 +663,7 @@ function $X(xpath, contextNode, resultType) { break; case "finally": assertNotAndWaitSuffix(i); - assertBlockIsPending("try", i); + assertBlockIsPending(lexStack, "try", i); tryDef = lexStack.top(); assertMatching(tryDef.cmdName, "try", i, tryDef.idx); if (blkDefFor(tryDef).finallyIdx) { @@ -405,7 +677,7 @@ function $X(xpath, contextNode, resultType) { break; case "endTry": assertNotAndWaitSuffix(i); - assertBlockIsPending("try", i); + assertBlockIsPending(lexStack, "try", i); tryDef = lexStack.pop(); assertMatching(tryDef.cmdName, "try", i, tryDef.idx); if (cmdTarget) { @@ -430,7 +702,7 @@ function $X(xpath, contextNode, resultType) { case "endWhile": case "endFor": case "endForeach": case "endForJson": case "endForXml": assertNotAndWaitSuffix(i); expectedCmd = curCmd.substr(3).toLowerCase(); - assertBlockIsPending(expectedCmd, i); + assertBlockIsPending(lexStack, expectedCmd, i); var beginDef = lexStack.pop(); assertMatching(beginDef.cmdName.toLowerCase(), expectedCmd, i, beginDef.idx); blkDefFor(beginDef).endIdx = i; // begin -> end @@ -452,14 +724,14 @@ function $X(xpath, contextNode, resultType) { break; case "return": assertNotAndWaitSuffix(i); - assertBlockIsPending("function", i, ", is not valid outside of a function/endFunction block"); + assertBlockIsPending(lexStack, "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); + assertBlockIsPending(lexStack, expectedCmd, i); var funcDef = lexStack.pop(); assertMatching(funcDef.cmdName.toLowerCase(), expectedCmd, i, funcDef.idx); if (cmdTarget) { @@ -487,20 +759,7 @@ function $X(xpath, contextNode, resultType) { } throw new SyntaxError(cmdErrors.join("; ")); } - //- 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)); - } - } + } // end of compileSelBlocksTestCase() // -------------------------------------------------------------------------------- @@ -608,8 +867,8 @@ function $X(xpath, contextNode, resultType) { } if (n !== 0) { // if n=0, execute the next command as usual - destIdx = idxHere() + n + 1; - assertIntraBlockJumpRestriction(idxHere(), destIdx); + destIdx = globIdx(localIdxHere()+n+1); + assertIntraBlockJumpRestriction(localIdxHere(), localIdxHere()+n+1); setNextCommand(destIdx); } }; @@ -617,9 +876,10 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doGoto = function(label) { assertRunning(); - assert(symbols[label]!==undefined, " Target label '" + label + "' is not found."); - assertIntraBlockJumpRestriction(idxHere(), symbols[label]); - setNextCommand(symbols[label]); + var symbolIndex= labelIdx(label); + assert(symbols[symbolIndex], " Target label '" + label + "' is not found."); + assertIntraBlockJumpRestriction(localIdxHere(), localIdx(symbols[symbolIndex])); + setNextCommand(symbols[symbolIndex]); }; Selenium.prototype.doGotoIf = function(condExpr, label) @@ -637,7 +897,7 @@ function $X(xpath, contextNode, resultType) { var ifDef = blkDefHere(); var ifState = { idx: idxHere(), elseIfItr: arrayIterator(ifDef.elseIfIdxs) }; activeBlockStack().push(ifState); - cascadeElseIf(ifState, condExpr); + this.cascadeElseIf(ifState, condExpr); }; Selenium.prototype.doElseIf = function(condExpr) { @@ -648,7 +908,7 @@ function $X(xpath, contextNode, resultType) { setNextCommand(blkDefAt(blkDefHere().ifIdx).endIdx); } else { - cascadeElseIf(ifState, condExpr); + this.cascadeElseIf(ifState, condExpr); } }; Selenium.prototype.doElse = function() @@ -668,9 +928,9 @@ function $X(xpath, contextNode, resultType) { // fall out of if-endIf }; - function cascadeElseIf(ifState, condExpr) { - assertCompilable("", condExpr, ";", "Invalid condition"); - if (!evalWithVars(condExpr)) { + Selenium.prototype.cascadeElseIf = function cascadeElseIf(ifState, condExpr) { + this.assertCompilable("", condExpr, ";", "Invalid condition"); + if (!this.evalWithVars(condExpr)) { // jump to next elseIf or else or endif var ifDef = blkDefFor(ifState); if (ifState.elseIfItr.hasNext()) { setNextCommand(ifState.elseIfItr.next()); } @@ -681,13 +941,13 @@ function $X(xpath, contextNode, resultType) { ifState.skipElseBlocks = true; // continue into if/elseIf block } - } + }; // ================================================================================ // throw the given Error Selenium.prototype.doThrow = function(err) { - err = evalWithVars(err); + err = this.evalWithVars(err); if (!(err instanceof Error)) { err = new SelblocksError(idxHere(), err); } @@ -711,7 +971,7 @@ function $X(xpath, contextNode, resultType) { // log an advisory about the active catch block if (tryDef.catchIdx) { - var errDcl = testCase.commands[tryDef.catchIdx].target; + var errDcl = localCommand( tryDef.catchIdx ).target; $$.LOG.debug(tryName + " catchable: " + (errDcl || "ANY")); } @@ -767,7 +1027,7 @@ function $X(xpath, contextNode, resultType) { // $$.tcf.bubbling = null; } if ($$.tcf.bubbling) { - reBubble(); + this.reBubble(); } else { $$.LOG.debug("no bubbling in process"); @@ -782,14 +1042,14 @@ function $X(xpath, contextNode, resultType) { // alter the behavior of Selenium error handling // returns true if catch/finally bubbling is active - function handleCommandError(err) + Selenium.prototype.handleCommandError = 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)) { + if (this.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; @@ -818,11 +1078,26 @@ function $X(xpath, contextNode, resultType) { } $$.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) + Selenium.prototype.bubbleCommand = function bubbleCommand(cmdIdx, _isContextBlockType) { + var self= this; + //- 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 (self.isMatchingCatch($$.tcf.bubbling.error, tryDef.catchIdx)) { + return true; + } + } + return hasUnspentFinally(stackFrame); + } + var tryState = bubbleToTryBlock(isTryWithMatchingOrFinally); var tryDef = blkDefFor(tryState); $$.tcf.bubbling = { mode: "command", srcIdx: cmdIdx, _isStopCriteria: _isContextBlockType }; @@ -838,35 +1113,21 @@ function $X(xpath, contextNode, resultType) { 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; + Selenium.prototype.isMatchingCatch = function isMatchingCatch(e, catchIdx) { + var errDcl = localCommand( catchIdx ).target; if (!errDcl) { return true; // no error specified means catch all errors } - var errExpr = evalWithVars(errDcl); + var errExpr = this.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) { @@ -876,6 +1137,12 @@ function $X(xpath, contextNode, resultType) { var tryState = unwindToBlock(_hasCriteria); while (!tryState && $$.tcf.nestingLevel > -1 && callStack.length > 1) { var callFrame = callStack.pop(); + var _result= storedVars._result; + storedVars= callFrame.savedVars; + storedVars._result= _result; + testCase= callFrame.testCase; + testCase.debugContext.testCase= testCase; + testCase.debugContext.debugIndex = localIdx( callFrame.returnIdx ); $$.LOG.info("function '" + callFrame.name + "' aborting due to error"); restoreVarState(callFrame.savedVars); tryState = unwindToBlock(_hasCriteria); @@ -893,11 +1160,11 @@ function $X(xpath, contextNode, resultType) { } // resume or conclude command/error bubbling - function reBubble() { + Selenium.prototype.reBubble = function reBubble() { if ($$.tcf.bubbling.mode === "error") { if ($$.tcf.nestingLevel > -1) { $$.LOG.debug("error-bubbling continuing..."); - handleCommandError($$.tcf.bubbling.error); + this.handleCommandError($$.tcf.bubbling.error); } else { $$.LOG.error("Error was not caught: '" + $$.tcf.bubbling.error.message + "'"); @@ -908,7 +1175,7 @@ function $X(xpath, contextNode, resultType) { else { // mode == "command" if (isBubblable()) { $$.LOG.debug("command-bubbling continuing..."); - bubbleCommand($$.tcf.bubbling.srcIdx, $$.tcf.bubbling._isStopCriteria); + this.bubbleCommand($$.tcf.bubbling.srcIdx, $$.tcf.bubbling._isStopCriteria); } else { $$.LOG.info("command-bubbling complete - suspended command executing now " + fmtCmdRef($$.tcf.bubbling.srcIdx)); @@ -916,10 +1183,10 @@ function $X(xpath, contextNode, resultType) { $$.tcf.bubbling = null; } } - } + }; // instigate or transform bubbling, as appropriate - function transitionBubbling(_isContextBlockType) + Selenium.prototype.transitionBubbling = function transitionBubbling(_isContextBlockType) { if ($$.tcf.bubbling) { // transform bubbling if ($$.tcf.bubbling.mode === "error") { @@ -935,29 +1202,29 @@ function $X(xpath, contextNode, resultType) { return true; } if (isBubblable(_isContextBlockType)) { // instigate bubbling - bubbleCommand(idxHere(), _isContextBlockType); + this.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); + var blkState = activeBlockStack().findEnclosing( + //- 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); + } + ); 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) { @@ -988,21 +1255,21 @@ function $X(xpath, contextNode, resultType) { bbl = "@" + ($$.tcf.bubbling.srcIdx+1) + " "; } var tryDef = blkDefFor(tryState); - var catchDcl = testCase.commands[tryDef.catchIdx].target; + var catchDcl = localCommand( tryDef.catchIdx ).target; return " :: " + bbl + catchDcl; } - // ================================================================================ Selenium.prototype.doWhile = function(condExpr) { + var self= this; enterLoop( function() { // validate assert(condExpr, " 'while' requires a condition expression."); - assertCompilable("", condExpr, ";", "Invalid condition"); + self.assertCompilable("", condExpr, ";", "Invalid condition"); return null; } ,function() { } // initialize - ,function() { return (evalWithVars(condExpr)); } // continue? + ,function() { return (self.evalWithVars(condExpr)); } // continue? ,function() { } // iterate ); }; @@ -1013,10 +1280,11 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doFor = function(forSpec) { + var self= this; enterLoop( function(loop) { // validate assert(forSpec, " 'for' requires: ; ; ."); - assertCompilable("for ( ", forSpec, " );", "Invalid loop parameters"); + self.assertCompilable("for ( ", forSpec, " );", "Invalid loop parameters"); var specs = iexpr.splitList(forSpec, ";"); assert(specs.length === 3, " 'for' requires ; ; ."); loop.initStmt = specs[0]; @@ -1027,9 +1295,9 @@ function $X(xpath, contextNode, resultType) { validateNames(localVarNames, "variable"); return localVarNames; } - ,function(loop) { evalWithVars(loop.initStmt); } // initialize - ,function(loop) { return (evalWithVars(loop.condExpr)); } // continue? - ,function(loop) { evalWithVars(loop.iterStmt); } // iterate + ,function(loop) { self.evalWithVars(loop.initStmt); } // initialize + ,function(loop) { return (self.evalWithVars(loop.condExpr)); } // continue? + ,function(loop) { self.evalWithVars(loop.iterStmt); } // iterate ); }; Selenium.prototype.doEndFor = function() { @@ -1048,16 +1316,16 @@ function $X(xpath, contextNode, resultType) { } return varNames; } - // ================================================================================ Selenium.prototype.doForeach = function(varName, valueExpr) { + var self= this; 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 + "]"); + self.assertCompilable("[ ", valueExpr, " ];", "Invalid value list"); + loop.values = self.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 } @@ -1075,19 +1343,18 @@ function $X(xpath, contextNode, resultType) { 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); + this.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); + this.loadVars(xmlReader, "XML element", filepath, selector); }; Selenium.prototype.doLoadVars = function(filepath, selector) { @@ -1096,10 +1363,10 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doLoadXmlVars(filepath, selector); }; - function loadVars(reader, desc, filepath, selector) + Selenium.prototype.loadVars = function loadVars(reader, desc, filepath, selector) { if (selector) { - assertCompilable("", selector, ";", "Invalid selector condition"); + this.assertCompilable("", selector, ";", "Invalid selector condition"); } reader.load(filepath); reader.next(); // read first varset and set values on storedVars @@ -1108,23 +1375,23 @@ function $X(xpath, contextNode, resultType) { + ' (A specific ' + desc + ' can be selected by specifying: name="value".)'); } - var result = evalWithVars(selector); + var result = this.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) { + while (!isEof && this.evalWithVars(selector) !== true) { reader.next(); // read next varset and set values on storedVars isEof = reader.EOF(); } - if (!evalWithVars(selector)) { + if (!this.evalWithVars(selector)) { notifyFatalHere(desc + " not found for selector expression: " + selector + "; in input file " + filepath); } - } + }; // ================================================================================ @@ -1223,7 +1490,7 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doContinue = function(condExpr) { - var loopState = dropToLoop(condExpr); + var loopState = this.dropToLoop(condExpr); if (loopState) { // jump back to top of loop for next iteration, if any var endCmd = blkDefFor(loopState); @@ -1231,7 +1498,7 @@ function $X(xpath, contextNode, resultType) { } }; Selenium.prototype.doBreak = function(condExpr) { - var loopState = dropToLoop(condExpr); + var loopState = this.dropToLoop(condExpr); if (loopState) { loopState.isComplete = true; // jump to bottom of loop for exit @@ -1241,46 +1508,69 @@ function $X(xpath, contextNode, resultType) { // Unwind the command stack to the inner-most active loop block // (unless the optional condition evaluates to false) - function dropToLoop(condExpr) + Selenium.prototype.dropToLoop = function dropToLoop(condExpr) { assertRunning(); if (condExpr) { - assertCompilable("", condExpr, ";", "Invalid condition"); + this.assertCompilable("", condExpr, ";", "Invalid condition"); } - if (transitionBubbling(Stack.isLoopBlock)) { + if (this.transitionBubbling(Stack.isLoopBlock)) { return; } - if (condExpr && !evalWithVars(condExpr)) { + if (condExpr && !this.evalWithVars(condExpr)) { return; } var loopState = activeBlockStack().unwindTo(Stack.isLoopBlock); return loopState; - } + }; // ================================================================================ Selenium.prototype.doCall = function(funcName, argSpec) { + var loop = currentTest || htmlTestRunner.currentTest; // See Selenium.prototype.doRollup() assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? if (argSpec) { - assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); + this.assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); } var funcIdx = symbols[funcName]; - assert(funcIdx!==undefined, " Function does not exist: " + funcName + "."); + assert(funcIdx, " Function does not exist: " + funcName + "."); var activeCallFrame = callStack.top(); if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function - restoreVarState(callStack.pop().savedVars); + var popped= callStack.pop(); + loop.commandError= popped.originalCommandError; + var _result= storedVars._result; + storedVars= popped.savedVars; //restoreVarState( popped.savedVars ); + storedVars._result= _result; + assert( testCase===popped.testCase, "The popped testCase is different." ); // Not sure why, but this seems to be true. } else { // save existing variable state and set args as local variables - var args = parseArgs(argSpec); - var savedVars = getVarStateFor(args); - setVars(args); - - callStack.push({ funcIdx: funcIdx, name: funcName, args: args, returnIdx: idxHere(), - savedVars: savedVars, blockStack: new Stack() }); + var args = this.parseArgs(argSpec); + var savedVars = storedVars; + storedVars = args; + + var originalCommandError= loop.commandError; + // There can be several cascading layers of these calls - one per function call level. + loop.commandError= function doCallCommandError( result ) { + this.commandError= originalCommandError; + // See also bubbleToTryBlock(..) + editor.selDebugger.pause(); + originalCommandError.call( this, result ); // I've restored this.commandError above *before* calling originalCommandError(), because: if this was a deeper function call then originalCommandError() will restore any previous version of this.commandError, and I don't want to step on its feet here + }; + + callStack.push( { + funcIdx: funcIdx, + name: funcName, + args: args, + returnIdx: idxHere(), + savedVars: savedVars, + blockStack: new Stack(), + testCase: testCase, + originalCommandError: originalCommandError + }); // jump to function body setNextCommand(funcIdx); } @@ -1292,8 +1582,7 @@ function $X(xpath, contextNode, resultType) { var funcDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx === idxHere()) { - // get parameter values - setVars(activeCallFrame.args); + //SelBlocks used to call setVars(activeCallFrame.args); here. But this was already handled in doCall(). } else { // no active call, skip around function body @@ -1307,19 +1596,19 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doFunction(scrName); }; Selenium.prototype.doReturn = function(value) { - returnFromFunction(null, value); + this.returnFromFunction(null, value); }; Selenium.prototype.doEndFunction = function(funcName) { - returnFromFunction(funcName); + this.returnFromFunction(funcName); }; Selenium.prototype.doEndScript = function(scrName) { - returnFromFunction(scrName); + this.returnFromFunction(scrName); }; - function returnFromFunction(funcName, returnVal) + Selenium.prototype.returnFromFunction = function(funcName, returnVal) { assertRunning(); - if (transitionBubbling(Stack.isFunctionBlock)) { + if (this.transitionBubbling(Stack.isFunctionBlock)) { return; } var endDef = blkDefHere(); @@ -1328,17 +1617,17 @@ function $X(xpath, contextNode, resultType) { // no active call, we're just skipping around a function block } else { - if (returnVal) { storedVars._result = evalWithVars(returnVal); } + if (returnVal) { storedVars._result = this.evalWithVars(returnVal); } activeCallFrame.isReturning = true; // jump back to call command setNextCommand(activeCallFrame.returnIdx); } - } + }; // ================================================================================ Selenium.prototype.doExitTest = function() { - if (transitionBubbling()) { + if (this.transitionBubbling()) { return; } // intercept command processing and simply stop test execution instead of executing the next command @@ -1347,8 +1636,7 @@ function $X(xpath, contextNode, resultType) { // ========= storedVars management ========= - - function evalWithVars(expr) { + Selenium.prototype.evalWithVars = function evalWithVars(expr) { var result = null; try { // EXTENSION REVIEWERS: Use of eval is consistent with the Selenium extension itself. @@ -1359,19 +1647,18 @@ function $X(xpath, contextNode, resultType) { notifyFatalErr(" While evaluating Javascript expression: " + expr, e); } return result; - } - - function parseArgs(argSpec) { // comma-sep -> new prop-set + }; + Selenium.prototype.parseArgs = function parseArgs(argSpec) { // 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]); + args[keyValue[0].trim()] = this.evalWithVars(keyValue[1]); } return args; - } + }; function initVarState(names) { // new -> storedVars(names) if (names) { var i; @@ -1440,7 +1727,21 @@ function $X(xpath, contextNode, resultType) { throw err; } function notifyFatalCmdRef(idx, msg) { notifyFatal(fmtCmdRef(idx) + msg); } - function notifyFatalHere(msg) { notifyFatal(fmtCurCmd() + msg); } + function notifyFatalHere(msg) { + // This may be called before testCase is set + var commandRef; + if( testCase===undefined ) { + commandRef= 'unknown step: '; + } + else { + // SelBlocks used fmtCurCmd() here. However, this + // may be called right after TestCaseDebugContext's nextCommand(), which (as intercepted by SelBlocksGlobal) sets testCase.debugContext.debugIndex to -1. Then + // fmtCurCmd() would fail (as it invokes idxHere() -> globIdx(-1). + var stepLocalIdx= localIdxHere(); + commandRef= fmtCmdRef( globIdx( Math.max(stepLocalIdx, 0) ) )+ ': '; + } + notifyFatal( commandRef+msg ); + } function assertCmd(idx, cond, msg) { if (!cond) { notifyFatalCmdRef(idx, msg); } } function assert(cond, msg) { if (!cond) { notifyFatalHere(msg); } } @@ -1454,20 +1755,29 @@ function $X(xpath, contextNode, resultType) { assert(activeIdx === expectedIdx, " unexpected command, active command was " + fmtCmdRef(activeIdx)); } - function assertCompilable(left, stmt, right, explanation) { + Selenium.prototype.assertCompilable = function assertCompilable(left, stmt, right, explanation) { try { - evalWithVars("function selblocksTemp() { " + left + stmt + right + " }"); + this.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]) + "]"); + var test= localCase(idx); + var commandIdx= localIdx(idx); + + return "@" +test.filename+ ': ' +(commandIdx+1) + ": " + fmtCommand( test.commands[commandIdx] ); + } + function fmtCommand(cmd) { + var c = cmd.command; + if (cmd.target) { c += "|" + cmd.target; } + if (cmd.value) { c += "|" + cmd.value; } + return '[' + c + ']'; } //================= Utils =============== @@ -1482,12 +1792,13 @@ function $X(xpath, contextNode, resultType) { // produce an iterator object for the given array function arrayIterator(arrayObject) { - return new function(ary) { + function ArrayIteratorClosure(ary) { var cur = 0; this.hasNext = function() { return (cur < ary.length); }; this.next = function() { if (this.hasNext()) { return ary[cur++]; } }; - }(arrayObject); - }; + } + return new ArrayIteratorClosure(arrayObject); + } // ==================== Data Files ==================== // Adapted from the datadriven plugin @@ -1515,7 +1826,7 @@ function $X(xpath, contextNode, resultType) { } curVars = 0; - varNames = attrNamesFor(varsets[0]); + varNames = XmlReader.attrNamesFor(varsets[0]); return varNames; }; @@ -1530,22 +1841,23 @@ function $X(xpath, contextNode, resultType) { return; } varsetIdx++; - $$.LOG.debug(varsetIdx + ") " + serializeXml(varsets[curVars])); // log each name & value + $$.LOG.debug(varsetIdx + ") " + XmlReader.serialize(varsets[curVars])); // log each name & value - var expected = countAttrs(varsets[0]); - var found = countAttrs(varsets[curVars]); + var expected = XmlReader.countAttrs(varsets[0]); + var found = XmlReader.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]); + XmlReader.setupStoredVars(varsets, varsetIdx, varsets[curVars]); curVars++; }; + } // end of XmlReader //- retrieve the names of each attribute on the given XML node - function attrNamesFor(node) { + XmlReader.attrNamesFor = function attrNamesFor(node) { var attrNames = []; var varAttrs = node.attributes; // NamedNodeMap var v; @@ -1553,15 +1865,16 @@ function $X(xpath, contextNode, resultType) { attrNames.push(varAttrs[v].nodeName); } return attrNames; - } + }; + //- determine how many attributes are present on the given node - function countAttrs(node) { + XmlReader.countAttrs = function countAttrs(node) { return node.attributes.length; - } - + }; + //- set selenium variables from given XML attributes - function setupStoredVars(node) { + XmlReader.setupStoredVars= function setupStoredVars(varsets, varsetIdx, node) { var varAttrs = node.attributes; // NamedNodeMap var v; for (v = 0; v < varAttrs.length; v++) { @@ -1574,17 +1887,16 @@ function $X(xpath, contextNode, resultType) { } storedVars[attr.nodeName] = attr.nodeValue; } - } + }; //- format the given XML node for display - function serializeXml(node) { + XmlReader.serializeXml = 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() @@ -1609,7 +1921,7 @@ function $X(xpath, contextNode, resultType) { } curVars = 0; - varNames = attrNamesFor(varsets[0]); + varNames = JSONReader.attrNamesFor(varsets[0]); return varNames; }; @@ -1624,42 +1936,43 @@ function $X(xpath, contextNode, resultType) { return; } varsetIdx++; - $$.LOG.debug(varsetIdx + ") " + serializeJson(varsets[curVars])); // log each name & value + $$.LOG.debug(varsetIdx + ") " + JSONReader.serializeJson(varsets[curVars])); // log each name & value - var expected = countAttrs(varsets[0]); - var found = countAttrs(varsets[curVars]); + var expected = JSONReader.countAttrs(varsets[0]); + var found = JSONReader.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]); + JSONReader.setupStoredVars(varsets, varsetIdx, varsets[curVars]); curVars++; }; + } // end of JSONReader - //- retrieve the names of each attribute on the given object - function attrNamesFor(obj) { + //- retrieve the names of each attribute on the given object + JSONReader.attrNamesFor = 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) { + JSONReader.countAttrs = 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) { + JSONReader.setupStoredVars = function setupStoredVars(varsets, varsetIdx, obj) { var attrName; for (attrName in obj) { if (null === varsets[0][attrName]) { @@ -1670,20 +1983,19 @@ function $X(xpath, contextNode, resultType) { } storedVars[attrName] = obj[attrName]; } - } + }; //- format the given JSON object for display - function serializeJson(obj) { + JSONReader.serializeJson = 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 testCasePath = testCase.file.path.replace("\\", "/", "g"); var i = testCasePath.lastIndexOf("/"); url = URL_PFX + testCasePath.substr(0, i) + "/" + filepath; } From ac760023e31cd5a80a7f519aefb27367ce4c05c5 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Wed, 31 Dec 2014 23:16:58 -0500 Subject: [PATCH 054/116] draft 2 I can call functions defined in one test case, from another test case. I can't run tests that have functions in them more than once or they'll always fail. When I run the script where the function is defined, it works the first time. If I run it again then things blow up. I can run the test that calls the function as many times as I want and it works. I wonder if I define another function in another test, if things would blow up when I ran the suite... --- .../chrome/content/extensions/selblocks.js | 24 +++++++++---------- sel-blocksTests/GlobalFunctions.html | 10 ++++++++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 71793e4..f05db3c 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -473,7 +473,7 @@ function $X(xpath, contextNode, resultType) { function setNextCommand(cmdIdx) { var idx= localIdx(cmdIdx); var localTestCase= localCase(cmdIdx); - assert( idx>=0 && idx< localTestCase.commands.length, + assert( idx >= 0 && idx < localTestCase.commands.length, " Cannot branch to non-existent command @" +cmdIdx ); branchIdx = cmdIdx; } @@ -857,7 +857,7 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doSkipNext = function(spec) { assertRunning(); - var n = parseInt(evalWithVars(spec), 10); + var n = parseInt(this.evalWithVars(spec), 10); if (isNaN(n)) { if (spec.trim() === "") { n = 1; } else { notifyFatalHere(" Requires a numeric value"); } @@ -885,7 +885,7 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doGotoIf = function(condExpr, label) { assertRunning(); - if (evalWithVars(condExpr)) { + if (this.evalWithVars(condExpr)) { this.doGoto(label); } }; @@ -981,7 +981,7 @@ function $X(xpath, contextNode, resultType) { if ($$.tcf.nestingLevel === 0) { // enable special command handling $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", - $$.handleAsTryBlock, { manageError: handleCommandError }); + $$.handleAsTryBlock, { manageError: this.handleCommandError }); } $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); // continue into try-block @@ -1048,7 +1048,7 @@ function $X(xpath, contextNode, resultType) { var tryDef = blkDefFor(tryState); if (tryState) { $$.LOG.debug("error encountered while: " + tryState.execPhase); - if (hasUnspentCatch(tryState)) { + if (this.hasUnspentCatch(tryState)) { if (this.isMatchingCatch(err, tryDef.catchIdx)) { // an expected kind of error has been caught $$.LOG.info("@" + (idxHere()+1) + ", error has been caught" + fmtCatching(tryState)); @@ -1064,7 +1064,7 @@ function $X(xpath, contextNode, resultType) { // 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)) { + if (self.hasUnspentFinally(tryState)) { $$.LOG.info("Bubbling suspended while finally block runs"); tryState.execPhase = "finallying"; tryState.hasFinaled = true; @@ -1089,19 +1089,19 @@ function $X(xpath, contextNode, resultType) { if (_isContextBlockType && _isContextBlockType(stackFrame)) { return true; } - if ($$.tcf.bubbling && $$.tcf.bubbling.mode === "error" && hasUnspentCatch(stackFrame)) { + if ($$.tcf.bubbling && $$.tcf.bubbling.mode === "error" && self.hasUnspentCatch(stackFrame)) { var tryDef = blkDefFor(stackFrame); if (self.isMatchingCatch($$.tcf.bubbling.error, tryDef.catchIdx)) { return true; } } - return hasUnspentFinally(stackFrame); + return self.hasUnspentFinally(stackFrame); } var tryState = bubbleToTryBlock(isTryWithMatchingOrFinally); var tryDef = blkDefFor(tryState); $$.tcf.bubbling = { mode: "command", srcIdx: cmdIdx, _isStopCriteria: _isContextBlockType }; - if (hasUnspentFinally(tryState)) { + if (self.hasUnspentFinally(tryState)) { $$.LOG.info("Command " + fmtCmdRef(cmdIdx) + ", suspended while finally block runs"); tryState.execPhase = "finallying"; tryState.hasFinaled = true; @@ -1227,10 +1227,10 @@ function $X(xpath, contextNode, resultType) { return canBubble; } - function hasUnspentCatch(tryState) { + Selenium.prototype.hasUnspentCatch = function hasUnspentCatch(tryState) { return (tryState && blkDefFor(tryState).catchIdx && !tryState.hasCaught); } - function hasUnspentFinally(tryState) { + Selenium.prototype.hasUnspentFinally = function hasUnspentFinally(tryState) { return (tryState && blkDefFor(tryState).finallyIdx && !tryState.hasFinaled); } @@ -1841,7 +1841,7 @@ function $X(xpath, contextNode, resultType) { return; } varsetIdx++; - $$.LOG.debug(varsetIdx + ") " + XmlReader.serialize(varsets[curVars])); // log each name & value + $$.LOG.debug(varsetIdx + ") " + XmlReader.serializeXml(varsets[curVars])); // log each name & value var expected = XmlReader.countAttrs(varsets[0]); var found = XmlReader.countAttrs(varsets[curVars]); diff --git a/sel-blocksTests/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html index da38020..adcc056 100644 --- a/sel-blocksTests/GlobalFunctions.html +++ b/sel-blocksTests/GlobalFunctions.html @@ -15,11 +15,21 @@ + + + + + + + + + + From 29e73e89effa2cdd19a61d7a61ae042a71ceccee Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Wed, 31 Dec 2014 23:29:35 -0500 Subject: [PATCH 055/116] adding tests functions are defined in two different test cases. After they've run, I can call the functions defined in them from a third test case. I can call the functions as many times as I want to from there. Things get weird when I'm trying to call the functions from the test case they're defined in. --- sel-blocksTests/CallGlobalFunction.html | 5 ++ sel-blocksTests/GlobalFunctions 2.html | 46 +++++++++++++++++++ sel-blocksTests/GlobalFunctionsTestSuite.html | 1 + 3 files changed, 52 insertions(+) create mode 100644 sel-blocksTests/GlobalFunctions 2.html diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html index a511df7..108bf33 100644 --- a/sel-blocksTests/CallGlobalFunction.html +++ b/sel-blocksTests/CallGlobalFunction.html @@ -35,6 +35,11 @@ + + + + +
setGlobalVar
openhttp://www.google.com
getEval globalStoredVars.aGlobalVar = "set";
openhttp://www.yahoo.com
endFunction globalStoredVars.aGlobalVar; set
calldoStuff
diff --git a/sel-blocksTests/GlobalFunctions 2.html b/sel-blocksTests/GlobalFunctions 2.html new file mode 100644 index 0000000..80832c9 --- /dev/null +++ b/sel-blocksTests/GlobalFunctions 2.html @@ -0,0 +1,46 @@ + + + + + + +GlobalFunctions 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobalFunctions 2
functiondoStuff
openhttps://github.com/
openhttp://en.wikipedia.org/wiki/Chili
endFunction
calldoStuff
assertLocationhttp://en.wikipedia.org/wiki/Chili
+ + diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index e088f8e..2a581a0 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -10,6 +10,7 @@
Test Suite
CreateGlobalVars
GlobalFunctions
GlobalFunctions 2
CallGlobalFunction
From e5a8f4e2b628c1ff76ac5a813ee4b19142b54532 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 1 Jan 2015 17:44:56 -0500 Subject: [PATCH 056/116] revert selblocks.js to master I've got better ideas about how to handle global functions. Throwing out the selblocks global stuff I merged in and reverting to the current master version. --- .../chrome/content/extensions/selblocks.js | 746 +++++------------- 1 file changed, 217 insertions(+), 529 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index f05db3c..f6ba739 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -123,18 +123,19 @@ function $X(xpath, contextNode, resultType) { // 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) { + 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 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); + if (c === t1.substr(t,1)) { + c = t2.substr(t,1); break; } } @@ -149,225 +150,39 @@ function $X(xpath, contextNode, resultType) { return t2[i]; } } - } else { + } + else { assert(false, "translate() function requires arguments of type String or Array"); } return null; }; - // ----- SelBlocksGlobal: - /** @param TestCase optional - * @return int 0-based index of given test case within the list of test cases - * of the test suite - **/ - function testCaseIdx(givenTestCase) { - var msg, - caseIndex; - givenTestCase = givenTestCase || testCase; - // Must not use assert() here, because that calls notifyFatalHere() which calls idxHere() - // which calls globIdx() which calls testCaseIdx() - if (typeof givenTestCase !== 'object') { - msg = "SelBlocks error: in testCaseIdx(), param givenTestCase is not an object, neither global testCase is."; - LOG.error(msg); - throw new Error(msg); - } - if (editor.app.testSuite.tests.length === 0) { - msg = "SelBlocks error: in testCaseIdx(), bad editor.app.testSuite.tests.length===0."; - LOG.error(msg); - throw new Error(msg); - } - for (caseIndex = editor.app.testSuite.tests.length - 1; caseIndex >= 0; caseIndex--) { - if (editor.app.testSuite.tests[caseIndex].content === givenTestCase) { - break; - } - } - if (caseIndex < 0) { - msg = "SelBlocks error: in testCaseIdx(), givenTestCase was not matched."; - LOG.error(msg); - throw new Error(msg); - } - return caseIndex; - } - - function logAndThrow(msg) { - var error = new Error(msg); - LOG.error(msg + "\n" + error.stack); - throw error; - } - /** This serves to generate unique global identifiers for test script commands. - * Results of this functions are usually values of symbols[] and other structures. - * @param {number} commandIndex 0-based index within givenTestCase (or within testCase). - * @param {TestCase} [givenTestCase] optional; using (current) testCase by default - // I'd rather use objects, but Javascript doesn't compare objects field by field - // - try javascript:a={first: 1}; b={first: 1}; a==b - @returns {string} global index of the command, in form testCaseIndex/commandIndex - */ - function globIdx(commandIndex, givenTestCase) { - givenTestCase = givenTestCase || testCase; - // Must not use assert() here, because that calls notifyFatalHere() which calls idxHere() which calls globIdx() - if (typeof commandIndex !== 'number' || commandIndex < 0) { - logAndThrow("SelBlocks error: in globIdx(), bad type/value of the first parameter commandIndex: " + commandIndex); - } - if (typeof givenTestCase !== 'object') { - logAndThrow("SelBlocks error: in globIdx(), bad type of the optional second parameter givenTestCase (or global testCase)."); - } - var caseIndex = testCaseIdx(givenTestCase); - return '' + caseIndex + '/' + commandIndex; - } - /** @return {number} (not a Number object) 0-based index of the respective command within its test case - * @param {string} globIdxValue Global index of a test command (test step). - */ - function localIdx(globIdxValue) { - var msg, - lastSlashIndex; - // Can't use assert() here, since assert indirectly calls fmtCmdRef() which calls localIdx() - recursion - if (typeof globIdxValue !== 'string') { - msg = 'globIdxValue must be a string, but got ' + (typeof globIdxValue) + ': ' + globIdxValue; - LOG.error(msg); - throw new Error(msg); - } - lastSlashIndex = globIdxValue.lastIndexOf('/'); - if (lastSlashIndex <= 0) { - msg = 'globIdxValue must contain "/" and not as the first character.'; - LOG.error(msg); - throw new Error(msg); - } - if (lastSlashIndex >= globIdxValue.length) { - msg = 'globIdxValue must contain "/" and not as the last character.'; - LOG.error(msg); - throw new Error(msg); - } - var afterSlash = globIdxValue.substr(lastSlashIndex + 1); - var afterSlashNumber = Number(afterSlash); - if (afterSlash !== '' + afterSlashNumber) { - msg = 'The part after "/" must be numeric.'; - LOG.error(msg); - throw new Error(msg); - } - var result = afterSlashNumber.valueOf(); - //"TODO:" - if (result < 0 || result >= editor.app.testSuite.tests[localCaseIdxPart(globIdxValue)].content.commands.length) { - msg = 'In localIdx("' + globIdxValue + '"), result ' + result + ' is not a valid command index'; - LOG.error(msg); - throw new Error(msg); - } - return result; - } - /**@param string result of globIdx() or of labelIdx() - * @return {number} (not a Number object) 0-based index of the test case (for the given global index) - * within the list of test cases (i.e. editor.app.testSuite.tests) - */ - function localCaseIdxPart(globIdxValue) { - assert(typeof globIdxValue === 'string', 'globIdxValue must be a string.'); - var lastSlashIndex = globIdxValue.lastIndexOf('/'); - assert(lastSlashIndex > 0, 'globIdxValue must contain "/" and not as the first character.'); - assert(lastSlashIndex < globIdxValue.length - 1, 'globIdxValue must contain "/" and not as the last character.'); - var beforeSlash = globIdxValue.substring(0, globIdxValue.lastIndexOf('/')); - var beforeSlashNumber = Number(beforeSlash); - assert('' + beforeSlash === '' + beforeSlashNumber, 'The part after "/" must be numeric.'); - var result = beforeSlashNumber.valueOf(); - assert(result >= 0 && result < editor.app.testSuite.tests.length, 'result not a valid index into editor.app.testSuite.tests.'); - return result; - } - /** global array of _usable_ test cases, set in compileSelBlocks(). - * It contains test cases in the same order as in editor.app.testSuite.tests[], - * but here they are as they come from editor.getTestCase() - **/ - var testCases = []; - - // @return TestCase test case for the given global index - function localCase(globIdxValue) { - var index = localCaseIdxPart(globIdxValue); - assert(index < testCases.length, 'case index: ' + index + ' but testCases[] has length ' + testCases.length); - return testCases[index]; - /* Following didn't work: - return editor.app.testSuite.tests[ localCaseIdxPart(globIdxValue) ].content; - */ - } - /** @return {Object} Command structure for given global index - * */ - function localCommand(globIdxValue) { - return localCase(globIdxValue).commands[localIdx(globIdxValue)]; - } - - /** This serves to generate and compare keys in symbols[] for label commands - * @param string label name - * @param TestCase test case where the label is; optional - using testCase by default - * @return string global label identifier in form 'test-case-index/label' - **/ - function labelIdx(label, givenTestCase) { - assert(typeof label === 'string', 'label must be a string.'); - givenTestCase = givenTestCase || testCase; - return '' + testCaseIdx(givenTestCase) + '/' + label; - } - // @TODO on insert, validate that function names are unique, i.e. no function overriding //=============== Call/Scope Stack handling =============== - /** @var object symbols */ - var symbols = {}; // command indexes stored by name: function names - /** @var {BlockDefs} Static command definitions stored by command index. Global, used for all test cases. */ - var blockDefs = null; // static command definitions stored by command index - /** @var {Stack} callStack Command execution stack */ - var callStack = null; // command execution stack + 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 // the idx of the currently executing command - // SelBlocksGlobal added param relativeShift and made it return a global, cross-test case index, rather than local (test-case specific) index - /** @param {number} [relativeShift=0] Relative shift to the current command's position - * @return {string} global command index - * */ - function idxHere(relativeShift) { - // Must not use assert() here, because that calls notifyFatalHere() which calls idxHere() - return globIdx(localIdxHere(relativeShift)); - } - /** @param {number} [relativeShift=0] Relative shift to the current command's position - * @return {number} Current command's position (within current test case), adjusted by relativeShift. Depending on relativeShift the result may not be a valid position. - * */ - function localIdxHere(relativeShift) { - relativeShift = relativeShift || 0; - return testCase.debugContext.debugIndex + relativeShift; + function idxHere() { + return testCase.debugContext.debugIndex; } // Command structure definitions, stored by command index - // SelBlocksGlobal: stored by command global index - i.e. value of idxHere() function BlockDefs() { - //@TODO use this.xxx=yyy, and define init() on BlockDefs.prototype. Then NetBeans navigation is easier. - /** @var {object} Serving as an associative array {globIdx => object of {any attributes, idx, cmdName}}. SelBlocksGlobal changed this from an array to an object. */ - var blkDefs = {}; - // initialize an entry in BlockDefs instance at the given command global index - /** @param {string} i Global index, a result of globIdx() function - * @param {Object} [attrs] Extra details to add, depending on the command: - * nature: 'if', 'try', 'loop', 'function' - * elseIfIdxs - array, used for 'if' - * ifIdx - used for 'else', 'elseIf' and 'endIf'; it's a global index of the matching 'if' step - * name - used for 'try', it's 'target' of the step (the 2nd column in Selenium IDE) - * tryIdx - used by 'catch', 'finally' and 'endTry', index of the matching 'try' - * finallyIdx - * beginIdx - used by 'continue', 'break', endWhile, endFor, endForeach, endForJson, endForXml; - * it's an index of the start of the current loop - * endIdx - * funcIdx - used by 'return', 'endfunction', 'endScript' - * @TODO check beginIdx and other fields - set after calls to blkDefFor(), blkDefAt() - * @return {object} A new entry just added to this collection. - * @see variable blkDefs - **/ - blkDefs.init = function BlockDefsInit(i, attrs) { - assert(typeof testCase.commands === 'object', 'BlockDefs::init() - testCase.commands is of bad type.'); - // @TODO assert regex numeric/numeric - assert(typeof i === 'string', 'BlockDefs::init() - param i must be a globIdx() result.'); - // @TODO change to use 'this' instead of 'blkDefs' - it will be clearer. + var blkDefs = []; + // initialize blockDef at the given command index + blkDefs.init = function(i, attrs) { blkDefs[i] = attrs || {}; blkDefs[i].idx = i; - // Following line is from original SelBlocks, here just for documentation - //blkDefs[i].cmdName = testCase.commands[i].command; - blkDefs[i].cmdName = localCase(i).commands[localIdx(i)].command; + blkDefs[i].cmdName = testCase.commands[i].command; return blkDefs[i]; }; return blkDefs; } // retrieve the blockDef at the given command idx - /** @param {string} idx Global index of a test step. */ function blkDefAt(idx) { return blockDefs[idx]; } @@ -386,24 +201,18 @@ function $X(xpath, contextNode, resultType) { // An Array object with stack functionality function Stack() { var stack = []; - stack.isEmpty = function isEmpty() { - return stack.length === 0; - }; - stack.top = function top() { - return stack[stack.length - 1]; - }; - stack.findEnclosing = function findEnclosing(_hasCriteria) { - return stack[stack.indexWhere(_hasCriteria)]; - }; - stack.indexWhere = function indexWhere(_hasCriteria) { // undefined if not found + 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--) { + for (i = stack.length-1; i >= 0; i--) { if (_hasCriteria(stack[i])) { return i; } } }; - stack.unwindTo = function unwindTo(_hasCriteria) { + stack.unwindTo = function(_hasCriteria) { if (stack.length === 0) { return null; } @@ -412,35 +221,23 @@ function $X(xpath, contextNode, resultType) { } return stack.top(); }; - stack.isHere = function isHere() { + 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"); - }; + 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 - // SelBLocksGlobal: This is a global index of the next command - set to a result of globIdx() var branchIdx = null; // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) - // See Selenium's {a6fd85ed-e919-4a43-a5af-8da18bda539f}/chrome/content/testCase.js - // This is for a head-intercept of TestCaseDebugContext.prototype.nextCommand(), and it adds support for SelBlocksGlobal branches (across test cases). - // We can't redefine/tail-intercept testCase.debugContext.nextCommand() at the time - // this SelBlocksGlobal source file is loaded, because testCase is not defined yet. Therefore we do it here - // on the first run of the enclosing tail intercept of Selenium.prototype.reset() below. - // And we intercept do it on the prototype, so that it applies to any test cases. function nextCommand() { if (!this.started) { this.started = true; @@ -449,14 +246,11 @@ function $X(xpath, contextNode, resultType) { else { if (branchIdx !== null) { $$.LOG.info("branch => " + fmtCmdRef(branchIdx)); - this.debugIndex = localIdx(branchIdx); - - testCase= this.testCase= localCase(branchIdx); - testCase.debugContext= this; + this.debugIndex = branchIdx; branchIdx = null; } else { - this.debugIndex++; // global removed this + this.debugIndex++; } } // skip over comments @@ -469,17 +263,12 @@ function $X(xpath, contextNode, resultType) { } return null; } - /** @param {string} globIdx value */ function setNextCommand(cmdIdx) { - var idx= localIdx(cmdIdx); - var localTestCase= localCase(cmdIdx); - assert( idx >= 0 && idx < localTestCase.commands.length, - " Cannot branch to non-existent command @" +cmdIdx ); + assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, + " Cannot branch to non-existent command @" + (cmdIdx+1)); branchIdx = cmdIdx; } -(function () { // wrapper makes testCaseDebugContextWasIntercepted private - var testCaseDebugContextWasIntercepted; // undefined or true // Selenium calls reset(): // * before each single (double-click) command execution // * before a testcase is run @@ -498,98 +287,37 @@ function $X(xpath, contextNode, resultType) { 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); - - //if( testCaseDebugContextWasIntercepted===undefined ) { - // // SelBlocksGlobal: This is a head-intercept, rather than interceptReplace as in SelBlocks 2.0.1, - // // and I'm intercepting TestCaseDebugContext.prototype.nextCommand() rather than testCase.debugContext.nextCommand() - // $$.LOG.debug("Configuring head intercept: TestCaseDebugContext.prototype.nextCommand()"); - // $$.fn.interceptBefore(TestCaseDebugContext.prototype, "nextCommand", nextCommand); - // - // testCaseDebugContextWasIntercepted= true; - //} }); -}()); // get the blockStack for the currently active callStack function activeBlockStack() { return callStack.top().blockStack; } + // ================================================================================ // Assemble block relationships and symbol locations function compileSelBlocks() { - symbols= {}; // Let's clear symbols - // Currently, this is called multiple times when Se IDE runs the whole test suite - // - once per each test case. No harm in that, only a bit of wasted CPU. - - //alert( 'testCase===editor.suiteTreeView.getCurrentTestCase(): ' +(testCase===editor.suiteTreeView.getCurrentTestCase()) ); // --> false! - //alert( 'testCase===editor.getTestCase(): ' +(testCase===editor.getTestCase()) ); //--> true! - var testCaseOriginal= testCase; - testCaseOriginal= editor.getTestCase(); - var testCaseOriginalIndex= -1; - testCases= []; - //alert( 'editor.app.getTestSuite()===editor.app.testSuite: ' +editor.app.getTestSuite()===editor.app.testSuite ); // => false - //alert( 'editor.app.testSuite.tests.indexOf( testCase): ' +editor.app.testSuite.tests.indexOf( testCase) ); // => -1 - // SelBlocksGlobal: I set blockDefs before looping through test cases, because it's global - for all test cases blockDefs = new BlockDefs(); - for( var testCaseIndex=0; testCaseIndex=0, "testCaseOriginalIndex mut be non-negative!"); - // In the following, do not pass testCases[testCaseOriginalIndex]. - // is not the same as editor.app.getTestSuite().tests[testCaseOriginalIndex], because - // Application.prototype.showTestCaseFromSuite(givenTestCase) calls this.setTestCase(givenTestCase.content) - editor.app.showTestCaseFromSuite( editor.app.getTestSuite().tests[testCaseOriginalIndex] ); - testCase.debugContext.testCase= testCase; - } - // end of compileSelBlocks() - // SelBlocksGlobal: Following three functions were inside compileSelBlocksTestCase(), but that doesn't follow JS strict mode. Two of them didn't have to be closures. assertBlockIsPending() used to be a closure, now it received parameter lexStack and is not a closure anymore. - //- command validation - function assertNotAndWaitSuffix(cmdIdx) { - assertCmd(cmdIdx, localCase(cmdIdx).commands[ localIdx(cmdIdx) ].command.indexOf("AndWait") === -1, - ", AndWait suffix is not valid for SelBlocks commands"); - } - //- active block validation - function assertBlockIsPending(lexStack, 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)); - } - // SelBlocksGlobal factored the following out of SelBlocks' compileSelBlocks(), to make 'testCase' not refer - // to global testCase - function compileSelBlocksTestCase( testCase ) { - // SelBlocksGlobal: I set lexStack here, since it's local stack per testCase (and only used during compilation) var lexStack = new Stack(); - // SelBlocksGlobal: Following loop variable commandIndex was renamed from 'i' in SelBlocks. - // I set variable 'i' to globIdx() value of commandIndex (i.e. of the original intended value of 'i'). This way - // the original SelBlocks code still uses variable 'i', so there are less merge conflicts. - var commandIndex, i; - for (commandIndex = 0; commandIndex < testCase.commands.length; commandIndex++) + var i; + for (i = 0; i < testCase.commands.length; i++) { - if (testCase.commands[commandIndex].type === "command") + if (testCase.commands[i].type === "command") { - var curCmd = testCase.commands[commandIndex].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[commandIndex].target; - i= globIdx(commandIndex, testCase); + var cmdTarget = testCase.commands[i].target; + var ifDef; var tryDef; var expectedCmd; @@ -597,7 +325,7 @@ function $X(xpath, contextNode, resultType) { { case "label": assertNotAndWaitSuffix(i); - symbols[ labelIdx(cmdTarget, testCase) ] = i; + symbols[cmdTarget] = i; break; case "goto": case "gotoIf": case "skipNext": assertNotAndWaitSuffix(i); @@ -609,7 +337,7 @@ function $X(xpath, contextNode, resultType) { break; case "elseIf": assertNotAndWaitSuffix(i); - assertBlockIsPending(lexStack, "elseIf", i, ", is not valid outside of an if/endIf block"); + 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; @@ -621,7 +349,7 @@ function $X(xpath, contextNode, resultType) { break; case "else": assertNotAndWaitSuffix(i); - assertBlockIsPending(lexStack, "if", i, ", is not valid outside of an if/endIf block"); + 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) { @@ -632,7 +360,7 @@ function $X(xpath, contextNode, resultType) { break; case "endIf": assertNotAndWaitSuffix(i); - assertBlockIsPending(lexStack, "if", i); + assertBlockIsPending("if", i); ifDef = lexStack.pop(); assertMatching(ifDef.cmdName, "if", i, ifDef.idx); blockDefs.init(i, { ifIdx: ifDef.idx }); // endIf -> if @@ -648,7 +376,7 @@ function $X(xpath, contextNode, resultType) { break; case "catch": assertNotAndWaitSuffix(i); - assertBlockIsPending(lexStack, "try", i, ", is not valid without a try block"); + assertBlockIsPending("try", i, ", is not valid without a try block"); tryDef = lexStack.top(); assertMatching(tryDef.cmdName, "try", i, tryDef.idx); if (blkDefFor(tryDef).catchIdx) { @@ -663,7 +391,7 @@ function $X(xpath, contextNode, resultType) { break; case "finally": assertNotAndWaitSuffix(i); - assertBlockIsPending(lexStack, "try", i); + assertBlockIsPending("try", i); tryDef = lexStack.top(); assertMatching(tryDef.cmdName, "try", i, tryDef.idx); if (blkDefFor(tryDef).finallyIdx) { @@ -677,7 +405,7 @@ function $X(xpath, contextNode, resultType) { break; case "endTry": assertNotAndWaitSuffix(i); - assertBlockIsPending(lexStack, "try", i); + assertBlockIsPending("try", i); tryDef = lexStack.pop(); assertMatching(tryDef.cmdName, "try", i, tryDef.idx); if (cmdTarget) { @@ -702,7 +430,7 @@ function $X(xpath, contextNode, resultType) { case "endWhile": case "endFor": case "endForeach": case "endForJson": case "endForXml": assertNotAndWaitSuffix(i); expectedCmd = curCmd.substr(3).toLowerCase(); - assertBlockIsPending(lexStack, expectedCmd, i); + assertBlockIsPending(expectedCmd, i); var beginDef = lexStack.pop(); assertMatching(beginDef.cmdName.toLowerCase(), expectedCmd, i, beginDef.idx); blkDefFor(beginDef).endIdx = i; // begin -> end @@ -724,14 +452,14 @@ function $X(xpath, contextNode, resultType) { break; case "return": assertNotAndWaitSuffix(i); - assertBlockIsPending(lexStack, "function", i, ", is not valid outside of a function/endFunction block"); + 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(lexStack, expectedCmd, i); + assertBlockIsPending(expectedCmd, i); var funcDef = lexStack.pop(); assertMatching(funcDef.cmdName.toLowerCase(), expectedCmd, i, funcDef.idx); if (cmdTarget) { @@ -759,7 +487,20 @@ function $X(xpath, contextNode, resultType) { } throw new SyntaxError(cmdErrors.join("; ")); } - } // end of compileSelBlocksTestCase() + //- 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)); + } + } // -------------------------------------------------------------------------------- @@ -857,7 +598,7 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doSkipNext = function(spec) { assertRunning(); - var n = parseInt(this.evalWithVars(spec), 10); + var n = parseInt(evalWithVars(spec), 10); if (isNaN(n)) { if (spec.trim() === "") { n = 1; } else { notifyFatalHere(" Requires a numeric value"); } @@ -867,8 +608,8 @@ function $X(xpath, contextNode, resultType) { } if (n !== 0) { // if n=0, execute the next command as usual - destIdx = globIdx(localIdxHere()+n+1); - assertIntraBlockJumpRestriction(localIdxHere(), localIdxHere()+n+1); + destIdx = idxHere() + n + 1; + assertIntraBlockJumpRestriction(idxHere(), destIdx); setNextCommand(destIdx); } }; @@ -876,16 +617,15 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doGoto = function(label) { assertRunning(); - var symbolIndex= labelIdx(label); - assert(symbols[symbolIndex], " Target label '" + label + "' is not found."); - assertIntraBlockJumpRestriction(localIdxHere(), localIdx(symbols[symbolIndex])); - setNextCommand(symbols[symbolIndex]); + 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 (this.evalWithVars(condExpr)) { + if (evalWithVars(condExpr)) { this.doGoto(label); } }; @@ -897,7 +637,7 @@ function $X(xpath, contextNode, resultType) { var ifDef = blkDefHere(); var ifState = { idx: idxHere(), elseIfItr: arrayIterator(ifDef.elseIfIdxs) }; activeBlockStack().push(ifState); - this.cascadeElseIf(ifState, condExpr); + cascadeElseIf(ifState, condExpr); }; Selenium.prototype.doElseIf = function(condExpr) { @@ -908,7 +648,7 @@ function $X(xpath, contextNode, resultType) { setNextCommand(blkDefAt(blkDefHere().ifIdx).endIdx); } else { - this.cascadeElseIf(ifState, condExpr); + cascadeElseIf(ifState, condExpr); } }; Selenium.prototype.doElse = function() @@ -928,9 +668,9 @@ function $X(xpath, contextNode, resultType) { // fall out of if-endIf }; - Selenium.prototype.cascadeElseIf = function cascadeElseIf(ifState, condExpr) { - this.assertCompilable("", condExpr, ";", "Invalid condition"); - if (!this.evalWithVars(condExpr)) { + 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()); } @@ -941,13 +681,13 @@ function $X(xpath, contextNode, resultType) { ifState.skipElseBlocks = true; // continue into if/elseIf block } - }; + } // ================================================================================ // throw the given Error Selenium.prototype.doThrow = function(err) { - err = this.evalWithVars(err); + err = evalWithVars(err); if (!(err instanceof Error)) { err = new SelblocksError(idxHere(), err); } @@ -971,7 +711,7 @@ function $X(xpath, contextNode, resultType) { // log an advisory about the active catch block if (tryDef.catchIdx) { - var errDcl = localCommand( tryDef.catchIdx ).target; + var errDcl = testCase.commands[tryDef.catchIdx].target; $$.LOG.debug(tryName + " catchable: " + (errDcl || "ANY")); } @@ -981,7 +721,7 @@ function $X(xpath, contextNode, resultType) { if ($$.tcf.nestingLevel === 0) { // enable special command handling $$.fn.interceptPush(editor.selDebugger.runner.currentTest, "resume", - $$.handleAsTryBlock, { manageError: this.handleCommandError }); + $$.handleAsTryBlock, { manageError: handleCommandError }); } $$.LOG.debug("++ try nesting: " + $$.tcf.nestingLevel); // continue into try-block @@ -1027,7 +767,7 @@ function $X(xpath, contextNode, resultType) { // $$.tcf.bubbling = null; } if ($$.tcf.bubbling) { - this.reBubble(); + reBubble(); } else { $$.LOG.debug("no bubbling in process"); @@ -1042,14 +782,14 @@ function $X(xpath, contextNode, resultType) { // alter the behavior of Selenium error handling // returns true if catch/finally bubbling is active - Selenium.prototype.handleCommandError = function handleCommandError(err) + function handleCommandError(err) { var tryState = bubbleToTryBlock(Stack.isTryBlock); var tryDef = blkDefFor(tryState); if (tryState) { $$.LOG.debug("error encountered while: " + tryState.execPhase); - if (this.hasUnspentCatch(tryState)) { - if (this.isMatchingCatch(err, tryDef.catchIdx)) { + 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; @@ -1064,7 +804,7 @@ function $X(xpath, contextNode, resultType) { // error not caught .. instigate bubbling $$.LOG.debug("error not caught, bubbling error: '" + err.message + "'"); $$.tcf.bubbling = { mode: "error", error: err, srcIdx: idxHere() }; - if (self.hasUnspentFinally(tryState)) { + if (hasUnspentFinally(tryState)) { $$.LOG.info("Bubbling suspended while finally block runs"); tryState.execPhase = "finallying"; tryState.hasFinaled = true; @@ -1078,30 +818,15 @@ function $X(xpath, contextNode, resultType) { } $$.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 - Selenium.prototype.bubbleCommand = function bubbleCommand(cmdIdx, _isContextBlockType) + function bubbleCommand(cmdIdx, _isContextBlockType) { - var self= this; - //- 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" && self.hasUnspentCatch(stackFrame)) { - var tryDef = blkDefFor(stackFrame); - if (self.isMatchingCatch($$.tcf.bubbling.error, tryDef.catchIdx)) { - return true; - } - } - return self.hasUnspentFinally(stackFrame); - } - var tryState = bubbleToTryBlock(isTryWithMatchingOrFinally); var tryDef = blkDefFor(tryState); $$.tcf.bubbling = { mode: "command", srcIdx: cmdIdx, _isStopCriteria: _isContextBlockType }; - if (self.hasUnspentFinally(tryState)) { + if (hasUnspentFinally(tryState)) { $$.LOG.info("Command " + fmtCmdRef(cmdIdx) + ", suspended while finally block runs"); tryState.execPhase = "finallying"; tryState.hasFinaled = true; @@ -1113,21 +838,35 @@ function $X(xpath, contextNode, resultType) { 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 - Selenium.prototype.isMatchingCatch = function isMatchingCatch(e, catchIdx) { - var errDcl = localCommand( catchIdx ).target; + function isMatchingCatch(e, catchIdx) { + var errDcl = testCase.commands[catchIdx].target; if (!errDcl) { return true; // no error specified means catch all errors } - var errExpr = this.evalWithVars(errDcl); + 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) { @@ -1137,12 +876,6 @@ function $X(xpath, contextNode, resultType) { var tryState = unwindToBlock(_hasCriteria); while (!tryState && $$.tcf.nestingLevel > -1 && callStack.length > 1) { var callFrame = callStack.pop(); - var _result= storedVars._result; - storedVars= callFrame.savedVars; - storedVars._result= _result; - testCase= callFrame.testCase; - testCase.debugContext.testCase= testCase; - testCase.debugContext.debugIndex = localIdx( callFrame.returnIdx ); $$.LOG.info("function '" + callFrame.name + "' aborting due to error"); restoreVarState(callFrame.savedVars); tryState = unwindToBlock(_hasCriteria); @@ -1160,11 +893,11 @@ function $X(xpath, contextNode, resultType) { } // resume or conclude command/error bubbling - Selenium.prototype.reBubble = function reBubble() { + function reBubble() { if ($$.tcf.bubbling.mode === "error") { if ($$.tcf.nestingLevel > -1) { $$.LOG.debug("error-bubbling continuing..."); - this.handleCommandError($$.tcf.bubbling.error); + handleCommandError($$.tcf.bubbling.error); } else { $$.LOG.error("Error was not caught: '" + $$.tcf.bubbling.error.message + "'"); @@ -1175,7 +908,7 @@ function $X(xpath, contextNode, resultType) { else { // mode == "command" if (isBubblable()) { $$.LOG.debug("command-bubbling continuing..."); - this.bubbleCommand($$.tcf.bubbling.srcIdx, $$.tcf.bubbling._isStopCriteria); + bubbleCommand($$.tcf.bubbling.srcIdx, $$.tcf.bubbling._isStopCriteria); } else { $$.LOG.info("command-bubbling complete - suspended command executing now " + fmtCmdRef($$.tcf.bubbling.srcIdx)); @@ -1183,10 +916,10 @@ function $X(xpath, contextNode, resultType) { $$.tcf.bubbling = null; } } - }; + } // instigate or transform bubbling, as appropriate - Selenium.prototype.transitionBubbling = function transitionBubbling(_isContextBlockType) + function transitionBubbling(_isContextBlockType) { if ($$.tcf.bubbling) { // transform bubbling if ($$.tcf.bubbling.mode === "error") { @@ -1202,35 +935,35 @@ function $X(xpath, contextNode, resultType) { return true; } if (isBubblable(_isContextBlockType)) { // instigate bubbling - this.bubbleCommand(idxHere(), _isContextBlockType); + 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( - //- 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); - } - ); + 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); + } } - Selenium.prototype.hasUnspentCatch = function hasUnspentCatch(tryState) { + function hasUnspentCatch(tryState) { return (tryState && blkDefFor(tryState).catchIdx && !tryState.hasCaught); } - Selenium.prototype.hasUnspentFinally = function hasUnspentFinally(tryState) { + function hasUnspentFinally(tryState) { return (tryState && blkDefFor(tryState).finallyIdx && !tryState.hasFinaled); } @@ -1255,21 +988,21 @@ function $X(xpath, contextNode, resultType) { bbl = "@" + ($$.tcf.bubbling.srcIdx+1) + " "; } var tryDef = blkDefFor(tryState); - var catchDcl = localCommand( tryDef.catchIdx ).target; + var catchDcl = testCase.commands[tryDef.catchIdx].target; return " :: " + bbl + catchDcl; } + // ================================================================================ Selenium.prototype.doWhile = function(condExpr) { - var self= this; enterLoop( function() { // validate assert(condExpr, " 'while' requires a condition expression."); - self.assertCompilable("", condExpr, ";", "Invalid condition"); + assertCompilable("", condExpr, ";", "Invalid condition"); return null; } ,function() { } // initialize - ,function() { return (self.evalWithVars(condExpr)); } // continue? + ,function() { return (evalWithVars(condExpr)); } // continue? ,function() { } // iterate ); }; @@ -1280,11 +1013,10 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doFor = function(forSpec) { - var self= this; enterLoop( function(loop) { // validate assert(forSpec, " 'for' requires: ; ; ."); - self.assertCompilable("for ( ", forSpec, " );", "Invalid loop parameters"); + assertCompilable("for ( ", forSpec, " );", "Invalid loop parameters"); var specs = iexpr.splitList(forSpec, ";"); assert(specs.length === 3, " 'for' requires ; ; ."); loop.initStmt = specs[0]; @@ -1295,9 +1027,9 @@ function $X(xpath, contextNode, resultType) { validateNames(localVarNames, "variable"); return localVarNames; } - ,function(loop) { self.evalWithVars(loop.initStmt); } // initialize - ,function(loop) { return (self.evalWithVars(loop.condExpr)); } // continue? - ,function(loop) { self.evalWithVars(loop.iterStmt); } // iterate + ,function(loop) { evalWithVars(loop.initStmt); } // initialize + ,function(loop) { return (evalWithVars(loop.condExpr)); } // continue? + ,function(loop) { evalWithVars(loop.iterStmt); } // iterate ); }; Selenium.prototype.doEndFor = function() { @@ -1316,16 +1048,16 @@ function $X(xpath, contextNode, resultType) { } return varNames; } + // ================================================================================ Selenium.prototype.doForeach = function(varName, valueExpr) { - var self= this; enterLoop( function(loop) { // validate assert(varName, " 'foreach' requires a variable name."); assert(valueExpr, " 'foreach' requires comma-separated values."); - self.assertCompilable("[ ", valueExpr, " ];", "Invalid value list"); - loop.values = self.evalWithVars("[" + valueExpr + "]"); + 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 } @@ -1343,18 +1075,19 @@ function $X(xpath, contextNode, resultType) { 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); - this.loadVars(jsonReader, "JSON object", filepath, selector); + 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); - this.loadVars(xmlReader, "XML element", filepath, selector); + loadVars(xmlReader, "XML element", filepath, selector); }; Selenium.prototype.doLoadVars = function(filepath, selector) { @@ -1363,10 +1096,10 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doLoadXmlVars(filepath, selector); }; - Selenium.prototype.loadVars = function loadVars(reader, desc, filepath, selector) + function loadVars(reader, desc, filepath, selector) { if (selector) { - this.assertCompilable("", selector, ";", "Invalid selector condition"); + assertCompilable("", selector, ";", "Invalid selector condition"); } reader.load(filepath); reader.next(); // read first varset and set values on storedVars @@ -1375,23 +1108,23 @@ function $X(xpath, contextNode, resultType) { + ' (A specific ' + desc + ' can be selected by specifying: name="value".)'); } - var result = this.evalWithVars(selector); + 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 && this.evalWithVars(selector) !== true) { + while (!isEof && evalWithVars(selector) !== true) { reader.next(); // read next varset and set values on storedVars isEof = reader.EOF(); } - if (!this.evalWithVars(selector)) { + if (!evalWithVars(selector)) { notifyFatalHere(desc + " not found for selector expression: " + selector + "; in input file " + filepath); } - }; + } // ================================================================================ @@ -1490,7 +1223,7 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doContinue = function(condExpr) { - var loopState = this.dropToLoop(condExpr); + var loopState = dropToLoop(condExpr); if (loopState) { // jump back to top of loop for next iteration, if any var endCmd = blkDefFor(loopState); @@ -1498,7 +1231,7 @@ function $X(xpath, contextNode, resultType) { } }; Selenium.prototype.doBreak = function(condExpr) { - var loopState = this.dropToLoop(condExpr); + var loopState = dropToLoop(condExpr); if (loopState) { loopState.isComplete = true; // jump to bottom of loop for exit @@ -1508,69 +1241,46 @@ function $X(xpath, contextNode, resultType) { // Unwind the command stack to the inner-most active loop block // (unless the optional condition evaluates to false) - Selenium.prototype.dropToLoop = function dropToLoop(condExpr) + function dropToLoop(condExpr) { assertRunning(); if (condExpr) { - this.assertCompilable("", condExpr, ";", "Invalid condition"); + assertCompilable("", condExpr, ";", "Invalid condition"); } - if (this.transitionBubbling(Stack.isLoopBlock)) { + if (transitionBubbling(Stack.isLoopBlock)) { return; } - if (condExpr && !this.evalWithVars(condExpr)) { + if (condExpr && !evalWithVars(condExpr)) { return; } var loopState = activeBlockStack().unwindTo(Stack.isLoopBlock); return loopState; - }; + } // ================================================================================ Selenium.prototype.doCall = function(funcName, argSpec) { - var loop = currentTest || htmlTestRunner.currentTest; // See Selenium.prototype.doRollup() assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? if (argSpec) { - this.assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); + assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); } var funcIdx = symbols[funcName]; - assert(funcIdx, " Function does not exist: " + funcName + "."); + assert(funcIdx!==undefined, " Function does not exist: " + funcName + "."); var activeCallFrame = callStack.top(); if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function - var popped= callStack.pop(); - loop.commandError= popped.originalCommandError; - var _result= storedVars._result; - storedVars= popped.savedVars; //restoreVarState( popped.savedVars ); - storedVars._result= _result; - assert( testCase===popped.testCase, "The popped testCase is different." ); // Not sure why, but this seems to be true. + restoreVarState(callStack.pop().savedVars); } else { // save existing variable state and set args as local variables - var args = this.parseArgs(argSpec); - var savedVars = storedVars; - storedVars = args; - - var originalCommandError= loop.commandError; - // There can be several cascading layers of these calls - one per function call level. - loop.commandError= function doCallCommandError( result ) { - this.commandError= originalCommandError; - // See also bubbleToTryBlock(..) - editor.selDebugger.pause(); - originalCommandError.call( this, result ); // I've restored this.commandError above *before* calling originalCommandError(), because: if this was a deeper function call then originalCommandError() will restore any previous version of this.commandError, and I don't want to step on its feet here - }; - - callStack.push( { - funcIdx: funcIdx, - name: funcName, - args: args, - returnIdx: idxHere(), - savedVars: savedVars, - blockStack: new Stack(), - testCase: testCase, - originalCommandError: originalCommandError - }); + var args = parseArgs(argSpec); + var savedVars = getVarStateFor(args); + setVars(args); + + callStack.push({ funcIdx: funcIdx, name: funcName, args: args, returnIdx: idxHere(), + savedVars: savedVars, blockStack: new Stack() }); // jump to function body setNextCommand(funcIdx); } @@ -1582,7 +1292,8 @@ function $X(xpath, contextNode, resultType) { var funcDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx === idxHere()) { - //SelBlocks used to call setVars(activeCallFrame.args); here. But this was already handled in doCall(). + // get parameter values + setVars(activeCallFrame.args); } else { // no active call, skip around function body @@ -1596,19 +1307,19 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doFunction(scrName); }; Selenium.prototype.doReturn = function(value) { - this.returnFromFunction(null, value); + returnFromFunction(null, value); }; Selenium.prototype.doEndFunction = function(funcName) { - this.returnFromFunction(funcName); + returnFromFunction(funcName); }; Selenium.prototype.doEndScript = function(scrName) { - this.returnFromFunction(scrName); + returnFromFunction(scrName); }; - Selenium.prototype.returnFromFunction = function(funcName, returnVal) + function returnFromFunction(funcName, returnVal) { assertRunning(); - if (this.transitionBubbling(Stack.isFunctionBlock)) { + if (transitionBubbling(Stack.isFunctionBlock)) { return; } var endDef = blkDefHere(); @@ -1617,17 +1328,17 @@ function $X(xpath, contextNode, resultType) { // no active call, we're just skipping around a function block } else { - if (returnVal) { storedVars._result = this.evalWithVars(returnVal); } + if (returnVal) { storedVars._result = evalWithVars(returnVal); } activeCallFrame.isReturning = true; // jump back to call command setNextCommand(activeCallFrame.returnIdx); } - }; + } // ================================================================================ Selenium.prototype.doExitTest = function() { - if (this.transitionBubbling()) { + if (transitionBubbling()) { return; } // intercept command processing and simply stop test execution instead of executing the next command @@ -1636,7 +1347,8 @@ function $X(xpath, contextNode, resultType) { // ========= storedVars management ========= - Selenium.prototype.evalWithVars = function evalWithVars(expr) { + + function evalWithVars(expr) { var result = null; try { // EXTENSION REVIEWERS: Use of eval is consistent with the Selenium extension itself. @@ -1647,18 +1359,19 @@ function $X(xpath, contextNode, resultType) { notifyFatalErr(" While evaluating Javascript expression: " + expr, e); } return result; - }; - Selenium.prototype.parseArgs = function parseArgs(argSpec) { // comma-sep -> new prop-set + } + + function parseArgs(argSpec) { // 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].trim()] = this.evalWithVars(keyValue[1]); + args[keyValue[0]] = evalWithVars(keyValue[1]); } return args; - }; + } function initVarState(names) { // new -> storedVars(names) if (names) { var i; @@ -1727,21 +1440,7 @@ function $X(xpath, contextNode, resultType) { throw err; } function notifyFatalCmdRef(idx, msg) { notifyFatal(fmtCmdRef(idx) + msg); } - function notifyFatalHere(msg) { - // This may be called before testCase is set - var commandRef; - if( testCase===undefined ) { - commandRef= 'unknown step: '; - } - else { - // SelBlocks used fmtCurCmd() here. However, this - // may be called right after TestCaseDebugContext's nextCommand(), which (as intercepted by SelBlocksGlobal) sets testCase.debugContext.debugIndex to -1. Then - // fmtCurCmd() would fail (as it invokes idxHere() -> globIdx(-1). - var stepLocalIdx= localIdxHere(); - commandRef= fmtCmdRef( globIdx( Math.max(stepLocalIdx, 0) ) )+ ': '; - } - notifyFatal( commandRef+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); } } @@ -1755,29 +1454,20 @@ function $X(xpath, contextNode, resultType) { assert(activeIdx === expectedIdx, " unexpected command, active command was " + fmtCmdRef(activeIdx)); } - Selenium.prototype.assertCompilable = function assertCompilable(left, stmt, right, explanation) { + function assertCompilable(left, stmt, right, explanation) { try { - this.evalWithVars("function selblocksTemp() { " + left + stmt + right + " }"); + 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) { - var test= localCase(idx); - var commandIdx= localIdx(idx); - - return "@" +test.filename+ ': ' +(commandIdx+1) + ": " + fmtCommand( test.commands[commandIdx] ); - } - function fmtCommand(cmd) { - var c = cmd.command; - if (cmd.target) { c += "|" + cmd.target; } - if (cmd.value) { c += "|" + cmd.value; } - return '[' + c + ']'; + return ("@" + (idx+1) + ": [" + $$.fmtCmd(testCase.commands[idx]) + "]"); } //================= Utils =============== @@ -1792,13 +1482,12 @@ function $X(xpath, contextNode, resultType) { // produce an iterator object for the given array function arrayIterator(arrayObject) { - function ArrayIteratorClosure(ary) { + return new function(ary) { var cur = 0; this.hasNext = function() { return (cur < ary.length); }; this.next = function() { if (this.hasNext()) { return ary[cur++]; } }; - } - return new ArrayIteratorClosure(arrayObject); - } + }(arrayObject); + }; // ==================== Data Files ==================== // Adapted from the datadriven plugin @@ -1826,7 +1515,7 @@ function $X(xpath, contextNode, resultType) { } curVars = 0; - varNames = XmlReader.attrNamesFor(varsets[0]); + varNames = attrNamesFor(varsets[0]); return varNames; }; @@ -1841,23 +1530,22 @@ function $X(xpath, contextNode, resultType) { return; } varsetIdx++; - $$.LOG.debug(varsetIdx + ") " + XmlReader.serializeXml(varsets[curVars])); // log each name & value + $$.LOG.debug(varsetIdx + ") " + serializeXml(varsets[curVars])); // log each name & value - var expected = XmlReader.countAttrs(varsets[0]); - var found = XmlReader.countAttrs(varsets[curVars]); + 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." ); } - XmlReader.setupStoredVars(varsets, varsetIdx, varsets[curVars]); + setupStoredVars(varsets[curVars]); curVars++; }; - } // end of XmlReader //- retrieve the names of each attribute on the given XML node - XmlReader.attrNamesFor = function attrNamesFor(node) { + function attrNamesFor(node) { var attrNames = []; var varAttrs = node.attributes; // NamedNodeMap var v; @@ -1865,16 +1553,15 @@ function $X(xpath, contextNode, resultType) { attrNames.push(varAttrs[v].nodeName); } return attrNames; - }; - + } //- determine how many attributes are present on the given node - XmlReader.countAttrs = function countAttrs(node) { + function countAttrs(node) { return node.attributes.length; - }; - + } + //- set selenium variables from given XML attributes - XmlReader.setupStoredVars= function setupStoredVars(varsets, varsetIdx, node) { + function setupStoredVars(node) { var varAttrs = node.attributes; // NamedNodeMap var v; for (v = 0; v < varAttrs.length; v++) { @@ -1887,16 +1574,17 @@ function $X(xpath, contextNode, resultType) { } storedVars[attr.nodeName] = attr.nodeValue; } - }; + } //- format the given XML node for display - XmlReader.serializeXml = function serializeXml(node) { + 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() @@ -1921,7 +1609,7 @@ function $X(xpath, contextNode, resultType) { } curVars = 0; - varNames = JSONReader.attrNamesFor(varsets[0]); + varNames = attrNamesFor(varsets[0]); return varNames; }; @@ -1936,43 +1624,42 @@ function $X(xpath, contextNode, resultType) { return; } varsetIdx++; - $$.LOG.debug(varsetIdx + ") " + JSONReader.serializeJson(varsets[curVars])); // log each name & value + $$.LOG.debug(varsetIdx + ") " + serializeJson(varsets[curVars])); // log each name & value - var expected = JSONReader.countAttrs(varsets[0]); - var found = JSONReader.countAttrs(varsets[curVars]); + 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." ); } - JSONReader.setupStoredVars(varsets, varsetIdx, varsets[curVars]); + setupStoredVars(varsets[curVars]); curVars++; }; - } // end of JSONReader - //- retrieve the names of each attribute on the given object - JSONReader.attrNamesFor = function attrNamesFor(obj) { + //- 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 - JSONReader.countAttrs = function countAttrs(obj) { + function countAttrs(obj) { var n = 0; var attrName; for (attrName in obj) { n++; } return n; - }; + } //- set selenium variables from given JSON attributes - JSONReader.setupStoredVars = function setupStoredVars(varsets, varsetIdx, obj) { + function setupStoredVars(obj) { var attrName; for (attrName in obj) { if (null === varsets[0][attrName]) { @@ -1983,19 +1670,20 @@ function $X(xpath, contextNode, resultType) { } storedVars[attrName] = obj[attrName]; } - }; + } //- format the given JSON object for display - JSONReader.serializeJson = function serializeJson(obj) { + 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) { - var testCasePath = testCase.file.path.replace("\\", "/", "g"); + testCasePath = testCase.file.path.replace("\\", "/", "g"); var i = testCasePath.lastIndexOf("/"); url = URL_PFX + testCasePath.substr(0, i) + "/" + filepath; } From 9358b32d27fc43580b2e96994817eea0ce3e8e51 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 1 Jan 2015 18:01:36 -0500 Subject: [PATCH 057/116] issue fixed: functions aren't global Since the blockdefs and stack are reset on a per testCase basis, the symbols need to be reset as well. If they're not, then the function names persist between test cases but the blockdefs don't. This causes selblocks to execute the range of indexes stored for the function, but using the commands array from the current case, which is obviously wrong. Resetting the symbols makes the behavior "functions aren't global", correct and fixes the bug. --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 1 + 1 file changed, 1 insertion(+) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index f6ba739..0814d7d 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -303,6 +303,7 @@ function $X(xpath, contextNode, resultType) { // Assemble block relationships and symbol locations function compileSelBlocks() { + symbols = {}; blockDefs = new BlockDefs(); var lexStack = new Stack(); var i; From 4ec8d62ffecfe76d9b263e91e63fabe110ba16ce Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 1 Jan 2015 19:06:35 -0500 Subject: [PATCH 058/116] Caching funcs from previous testCases This holds a naive clone of the symbols, commands, and blockDefs for each test suite as it is run through "compileSelBlocks". The cache is private to the closure where selblocks is built so, it can't be tampered with from the outside. --- .../chrome/content/extensions/selblocks.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 0814d7d..8a57ec7 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -163,6 +163,11 @@ function $X(xpath, contextNode, resultType) { 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 + /** + * selblocks test case functions cache, to allow calling funcs across the + * entire suite. + */ + var cachedCommands = Object.create(null); // the idx of the currently executing command function idxHere() { @@ -488,6 +493,15 @@ function $X(xpath, contextNode, resultType) { } throw new SyntaxError(cmdErrors.join("; ")); } + (function cacheCommands() { + var _mytitle = (testCase.title) ? testCase.title : "untitled"; + cachedCommands[_mytitle] = { + 'symbols' : naiveClone(symbols), + 'commands' : naiveClone(testCase.commands), + 'blockDefs' : naiveClone(blockDefs) + }; + }()); + //console.dir(cachedCommands); //- command validation function assertNotAndWaitSuffix(cmdIdx) { assertCmd(cmdIdx, (testCase.commands[cmdIdx].command.indexOf("AndWait") === -1), @@ -501,6 +515,9 @@ function $X(xpath, contextNode, resultType) { function assertMatching(curCmd, expectedCmd, cmdIdx, pendIdx) { assertCmd(cmdIdx, curCmd === expectedCmd, ", does not match command " + fmtCmdRef(pendIdx)); } + function naiveClone(symbols) { + return JSON.parse(JSON.stringify(symbols)); + } } // -------------------------------------------------------------------------------- From a7efd2f44368afbc87891882178c511973fdcf66 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 1 Jan 2015 19:33:16 -0500 Subject: [PATCH 059/116] Beginning specs for calling caseName.fn calling functions from other test cases should require qualifying the function name with the test case title, that way two cases could have a function with the same name and not collide. Think of it like two namespaces. Currently, this doesn't execute functions in other cases, it just uses the cache to lookup the symbol for the current case. --- .../chrome/content/extensions/selblocks.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 8a57ec7..26f30ae 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -495,6 +495,7 @@ function $X(xpath, contextNode, resultType) { } (function cacheCommands() { var _mytitle = (testCase.title) ? testCase.title : "untitled"; + cachedCommands.currentCaseTitle = _mytitle; cachedCommands[_mytitle] = { 'symbols' : naiveClone(symbols), 'commands' : naiveClone(testCase.commands), @@ -1279,11 +1280,18 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doCall = function(funcName, argSpec) { + var funcIdx, caseName; assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? if (argSpec) { assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); } - var funcIdx = symbols[funcName]; + if(funcName.match(/[.]/)) { + caseName = funcName.split(".")[0]; + funcName = funcName.split(".")[1]; + } else { + caseName = cachedCommands.currentCaseTitle; + } + funcIdx = cachedCommands[caseName].symbols[funcName]; assert(funcIdx!==undefined, " Function does not exist: " + funcName + "."); var activeCallFrame = callStack.top(); From 071298bc77484779db0a8d7d2aaf5769f0cb8748 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 1 Jan 2015 19:46:40 -0500 Subject: [PATCH 060/116] updates test to use namespaced funcs --- sel-blocksTests/CallGlobalFunction.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html index 108bf33..cb40fb0 100644 --- a/sel-blocksTests/CallGlobalFunction.html +++ b/sel-blocksTests/CallGlobalFunction.html @@ -27,7 +27,7 @@ call - setGlobalVar + GlobalFunctions.setGlobalVar @@ -37,7 +37,7 @@ call - doStuff + GlobalFunctions 2.doStuff From 789c42bd0deb8ae6e041f49c16ca64987b5072d5 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 1 Jan 2015 19:48:45 -0500 Subject: [PATCH 061/116] reintroduces cross case bug calling a function in the current case works as expected. Calling a function with it's qualified name in another test case will exhibit the same behavior as was happening before we reset the symbols for each case. --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 26f30ae..36d6b7a 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1280,19 +1280,20 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doCall = function(funcName, argSpec) { - var funcIdx, caseName; + var funcIdx, fName, caseName; assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? if (argSpec) { assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); } if(funcName.match(/[.]/)) { caseName = funcName.split(".")[0]; - funcName = funcName.split(".")[1]; + fName = funcName.split(".")[1]; } else { caseName = cachedCommands.currentCaseTitle; + fName = funcName; } - funcIdx = cachedCommands[caseName].symbols[funcName]; - assert(funcIdx!==undefined, " Function does not exist: " + funcName + "."); + funcIdx = cachedCommands[caseName].symbols[fName]; + assert(funcIdx!==undefined, " Function does not exist: " + funcName); var activeCallFrame = callStack.top(); if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { From 38c40460eaab8a05f81522cb5e3021f3ece7ff74 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Thu, 1 Jan 2015 20:02:50 -0500 Subject: [PATCH 062/116] adding active case property to cache --- .../chrome/content/extensions/selblocks.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 36d6b7a..085d68c 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -244,6 +244,7 @@ function $X(xpath, contextNode, resultType) { // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) function nextCommand() { + var activeCase = cachedCommands.activeCase; if (!this.started) { this.started = true; this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; @@ -1286,19 +1287,21 @@ function $X(xpath, contextNode, resultType) { assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); } if(funcName.match(/[.]/)) { - caseName = funcName.split(".")[0]; - fName = funcName.split(".")[1]; + caseName = String(funcName.split(".")[0]); + fName = String(funcName.split(".")[1]); } else { - caseName = cachedCommands.currentCaseTitle; - fName = funcName; + caseName = String(cachedCommands.currentCaseTitle); + fName = String(funcName); } funcIdx = cachedCommands[caseName].symbols[fName]; assert(funcIdx!==undefined, " Function does not exist: " + funcName); + cachedCommands.activeCase = cachedCommands[String(caseName)]; var activeCallFrame = callStack.top(); if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function restoreVarState(callStack.pop().savedVars); + cachedCommands.activeCase = cachedCommands.currentCaseTitle; } else { // save existing variable state and set args as local variables From 89a7571c1e91e88b0d7eb6e8a2e8ff7c73021bd6 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 01:52:08 -0500 Subject: [PATCH 063/116] offsetting command indexes I don't want the "function" or "endfunction" to be in the same row as the "call". --- sel-blocksTests/CallGlobalFunction.html | 10 ++++++++++ sel-blocksTests/CreateGlobalVars.html | 11 ++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html index cb40fb0..5066a9a 100644 --- a/sel-blocksTests/CallGlobalFunction.html +++ b/sel-blocksTests/CallGlobalFunction.html @@ -15,6 +15,16 @@ globalStoredVars.aGlobalVar = "reset"; + + getEval + globalStoredVars.aGlobalVar = "reset"; + + + + getEval + globalStoredVars.aGlobalVar = "reset"; + + assertNotEval globalStoredVars.aGlobalVar; diff --git a/sel-blocksTests/CreateGlobalVars.html b/sel-blocksTests/CreateGlobalVars.html index 969fed7..af27f19 100644 --- a/sel-blocksTests/CreateGlobalVars.html +++ b/sel-blocksTests/CreateGlobalVars.html @@ -15,7 +15,16 @@ globalStoredVars = {}; - + + getEval + globalStoredVars = {}; + + + + getEval + globalStoredVars = {}; + + From 69d9d1cf8ab535fb68467b3bdd9c28ec97020486 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 01:53:19 -0500 Subject: [PATCH 064/116] It works! --- .../chrome/content/extensions/selblocks.js | 108 ++++++++++++------ 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 085d68c..7004770 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -82,6 +82,9 @@ function $X(xpath, contextNode, resultType) { // selbocks name-space (function($$){ + function naiveClone(symbols) { + return JSON.parse(JSON.stringify(symbols)); + } // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: @@ -157,21 +160,56 @@ 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 /** - * selblocks test case functions cache, to allow calling funcs across the - * entire suite. + * 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 cachedCommands = Object.create(null); + 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 = 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 @@ -189,7 +227,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() { @@ -244,34 +288,44 @@ function $X(xpath, contextNode, resultType) { // if testCase.nextCommand() ever changes, this will need to be revisited // (current as of: selenium-ide-2.4.0) function nextCommand() { - var activeCase = cachedCommands.activeCase; 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]; + while (cachedCommandsData.commandIndex < cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands.length) { + var command = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands[cachedCommandsData.commandIndex]; if (command.type === "command") { return command; } - this.debugIndex++; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex++; + } + cachedCommandsData.commandIndex++; } return null; } 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; } @@ -309,6 +363,7 @@ function $X(xpath, contextNode, resultType) { // Assemble block relationships and symbol locations function compileSelBlocks() { + cachedCommandsData.init(); symbols = {}; blockDefs = new BlockDefs(); var lexStack = new Stack(); @@ -494,16 +549,7 @@ function $X(xpath, contextNode, resultType) { } throw new SyntaxError(cmdErrors.join("; ")); } - (function cacheCommands() { - var _mytitle = (testCase.title) ? testCase.title : "untitled"; - cachedCommands.currentCaseTitle = _mytitle; - cachedCommands[_mytitle] = { - 'symbols' : naiveClone(symbols), - 'commands' : naiveClone(testCase.commands), - 'blockDefs' : naiveClone(blockDefs) - }; - }()); - //console.dir(cachedCommands); + cachedCommandsData.cacheCommands(symbols, testCase.commands, blockDefs); //- command validation function assertNotAndWaitSuffix(cmdIdx) { assertCmd(cmdIdx, (testCase.commands[cmdIdx].command.indexOf("AndWait") === -1), @@ -517,9 +563,6 @@ function $X(xpath, contextNode, resultType) { function assertMatching(curCmd, expectedCmd, cmdIdx, pendIdx) { assertCmd(cmdIdx, curCmd === expectedCmd, ", does not match command " + fmtCmdRef(pendIdx)); } - function naiveClone(symbols) { - return JSON.parse(JSON.stringify(symbols)); - } } // -------------------------------------------------------------------------------- @@ -1290,18 +1333,18 @@ function $X(xpath, contextNode, resultType) { caseName = String(funcName.split(".")[0]); fName = String(funcName.split(".")[1]); } else { - caseName = String(cachedCommands.currentCaseTitle); + caseName = String(cachedCommandsData.activeCaseTitle); fName = String(funcName); } - funcIdx = cachedCommands[caseName].symbols[fName]; + funcIdx = cachedCommandsData.suites[caseName].symbols[fName]; assert(funcIdx!==undefined, " Function does not exist: " + funcName); - cachedCommands.activeCase = cachedCommands[String(caseName)]; + cachedCommandsData.activeCaseTitle = String(caseName); var activeCallFrame = callStack.top(); if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); restoreVarState(callStack.pop().savedVars); - cachedCommands.activeCase = cachedCommands.currentCaseTitle; } else { // save existing variable state and set args as local variables @@ -1309,7 +1352,7 @@ function $X(xpath, contextNode, resultType) { var savedVars = getVarStateFor(args); setVars(args); - callStack.push({ funcIdx: funcIdx, name: funcName, args: args, returnIdx: idxHere(), + callStack.push({ funcIdx: funcIdx, name: fName, args: args, returnIdx: idxHere(), savedVars: savedVars, blockStack: new Stack() }); // jump to function body setNextCommand(funcIdx); @@ -1361,6 +1404,7 @@ function $X(xpath, contextNode, resultType) { if (returnVal) { storedVars._result = evalWithVars(returnVal); } activeCallFrame.isReturning = true; // jump back to call command + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); setNextCommand(activeCallFrame.returnIdx); } } From 9ac20361f216aa1da03eba08f1354cf2ff472687 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 01:59:19 -0500 Subject: [PATCH 065/116] removing unused function I'd rather return clones of the commands, since we're running rows from functions more than once. My naive clone function destroyed command objects though. --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 7004770..d298d16 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -82,9 +82,6 @@ function $X(xpath, contextNode, resultType) { // selbocks name-space (function($$){ - function naiveClone(symbols) { - return JSON.parse(JSON.stringify(symbols)); - } // =============== Javascript extensions as script helpers =============== // EXTENSION REVIEWERS: From a557cf0159d084ccb123ac337befa6ad7022375c Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 15:18:52 -0500 Subject: [PATCH 066/116] Draft 1: define fn params bugged, when parameter defaults to undefined and fn is called without specifying said param, storedVars will not be restored on exiting fn execution in some cases. --- .../chrome/content/extensions/selblocks.js | 61 ++++++++++++-- .../DefineFunctionParameters - Base.html | 83 +++++++++++++++++++ sel-blocksTests/GlobalFunctionsTestSuite.html | 1 + 3 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 sel-blocksTests/DefineFunctionParameters - Base.html diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index d298d16..d1f08bc 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1355,14 +1355,17 @@ function $X(xpath, contextNode, resultType) { setNextCommand(funcIdx); } }; - Selenium.prototype.doFunction = function(funcName) + Selenium.prototype.doFunction = function(funcName, paramString) { assertRunning(); - + var params; var funcDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx === idxHere()) { - // get parameter values + params = parseArgs(paramString, "suppress variable expansion"); + // set default values supplied in function definition + setVars(params); + // overwrite local variables with the supplied values from the call setVars(activeCallFrame.args); } else { @@ -1431,15 +1434,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; } @@ -1453,6 +1478,15 @@ function $X(xpath, contextNode, resultType) { } } } + /** + * 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; @@ -1461,6 +1495,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) { @@ -1471,6 +1512,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) { diff --git a/sel-blocksTests/DefineFunctionParameters - Base.html b/sel-blocksTests/DefineFunctionParameters - Base.html new file mode 100644 index 0000000..0fe1f85 --- /dev/null +++ b/sel-blocksTests/DefineFunctionParameters - Base.html @@ -0,0 +1,83 @@ + + + + + + +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/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index 2a581a0..de6ac1a 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -12,6 +12,7 @@
GlobalFunctions GlobalFunctions 2 CallGlobalFunction +DefineFunctionParameters - Base From 2226f6e49be968759741744f8e5e049712b47112 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 16:58:12 -0500 Subject: [PATCH 067/116] moved saving vars into doFunction we have to cache the values of all storedVars that exist in the function signature, since we're initializing them to undefined for the function block. If we don't cache all the storedVars spec'd in the sig., then when the call completes only the args specified in the call will be restored while the unspecified params will be left as undefined on the storedVars object, or leak whatever value may have been assigned to them in the function call. --- .../chrome/content/extensions/selblocks.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index d1f08bc..a1b10c7 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1344,13 +1344,12 @@ function $X(xpath, contextNode, resultType) { 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: fName, args: args, returnIdx: idxHere(), - savedVars: savedVars, blockStack: new Stack() }); + savedVars: {}, blockStack: new Stack() }); // jump to function body setNextCommand(funcIdx); } @@ -1358,14 +1357,18 @@ function $X(xpath, contextNode, resultType) { Selenium.prototype.doFunction = function(funcName, paramString) { assertRunning(); - var params; + var params, savedVars; var funcDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx === idxHere()) { 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 with the supplied values from the call + // overwrite local variables and defaults with the supplied values from + // the call setVars(activeCallFrame.args); } else { From 1939111b2621d1300033ec8b8e89ed13aea08144 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 17:27:15 -0500 Subject: [PATCH 068/116] removed comment about fixed bug --- sel-blocksTests/DefineFunctionParameters - Base.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/sel-blocksTests/DefineFunctionParameters - Base.html b/sel-blocksTests/DefineFunctionParameters - Base.html index 0fe1f85..a7b8cf5 100644 --- a/sel-blocksTests/DefineFunctionParameters - Base.html +++ b/sel-blocksTests/DefineFunctionParameters - Base.html @@ -66,8 +66,6 @@ "${x}" === "original"; true - - assertEval storedVars.y === undefined From 5efbc6b02527b730f6ed27f2beca2092246b03f6 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 17:27:44 -0500 Subject: [PATCH 069/116] adds test for funcs with default values --- ...ctionParameters - With Default Values.html | 206 ++++++++++++++++++ sel-blocksTests/GlobalFunctionsTestSuite.html | 1 + 2 files changed, 207 insertions(+) create mode 100644 sel-blocksTests/DefineFunctionParameters - With Default Values.html diff --git a/sel-blocksTests/DefineFunctionParameters - With Default Values.html b/sel-blocksTests/DefineFunctionParameters - With Default Values.html new file mode 100644 index 0000000..2e10e74 --- /dev/null +++ b/sel-blocksTests/DefineFunctionParameters - With Default Values.html @@ -0,0 +1,206 @@ + + + + + + +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
storenonlocalleak
endFunction
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/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index de6ac1a..8a15ec9 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -13,6 +13,7 @@ GlobalFunctions 2 CallGlobalFunction DefineFunctionParameters - Base +DefineFunctionParameters - With Default Values From a4f57d375ae533743e945044c40f53fd6b6e819c Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 17:40:49 -0500 Subject: [PATCH 070/116] tests that default values respected the tests now check that parameters can have default values specified, that those values will be respected, and that parameters automatically become function scoped variables (not just the specified args). --- ...ctionParameters - With Default Values.html | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/sel-blocksTests/DefineFunctionParameters - With Default Values.html b/sel-blocksTests/DefineFunctionParameters - With Default Values.html index 2e10e74..cbf9f1d 100644 --- a/sel-blocksTests/DefineFunctionParameters - With Default Values.html +++ b/sel-blocksTests/DefineFunctionParameters - With Default Values.html @@ -31,6 +31,7 @@ "${y}" === "original"; true + function leakTest @@ -46,16 +47,58 @@ overwritten y + + endFunction + + + + + + function + defaultsTest + x="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 - nonlocal - leak + "overwritten" + y + + + assertEval + ${y} === "overwritten" + true endFunction + + + call + defaultsTest + + call @@ -96,7 +139,7 @@ call leakTest - y="overwritten" + y = "overwritten" assertEval @@ -132,7 +175,7 @@ call leakTest - x="overwritten" + x = "overwritten" assertEval From a17b481f0c821b8b09b8ac18560a2673c65ca336 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 19:00:35 -0500 Subject: [PATCH 071/116] overriding current command current command is supposed to return the current command being executed. This has to be overridden in order to return the correct command object. --- .../chrome/content/extensions/selblocks.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index a1b10c7..fd90bb1 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -325,7 +325,15 @@ function $X(xpath, contextNode, resultType) { " Cannot branch to non-existent command " + String(cachedCommandsData.activeCaseTitle) + " @" + (cmdIdx+1)); branchIdx = cmdIdx; } - + function currentCommand () { + var theCase = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)]; + var theIndex = cachedCommandsData.commandIndex; + var command = theCase.commands[theIndex]; + if (!command) { + testCase.log.warn("currentCommand() not found: commands.length=" + theCase.commands.length + ", debugIndex=" + theIndex); + } + return command; + } // Selenium calls reset(): // * before each single (double-click) command execution // * before a testcase is run @@ -349,6 +357,7 @@ function $X(xpath, contextNode, resultType) { // 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); + $$.fn.interceptReplace(testCase.debugContext, "currentCommand", currentCommand); }); // get the blockStack for the currently active callStack From 64ba36e837b64de9118965657254ee7bb8b20920 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 19:18:21 -0500 Subject: [PATCH 072/116] changed test for leaking values Functions scope their defined parameters by name, all other variables leak to the containing scope. The current behavior in master branch is that all arguments passed in are arbitrarily scoped but, any new variables defined inside of the function block will leak to the global storedVariables and persist after the function returns. This new behavior is more consistent with the model presented by JavaScript, where defining variables without the var keyword will leak them into the containing scope. Given that the parameters are automatically scoped to the function, there is no need to define them and they will not leak. This is the exact behavior exhibited by selblocks functions now. We can implement block scoping for all variables by cloning storedVars at the beginning of function execution, then replacing it afterward. This is not the current behavior though, and would more likely break existing tests that count on being able to set global variables from within a function. --- sel-blocksTests/function.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sel-blocksTests/function.html b/sel-blocksTests/function.html index 5642472..a4112c0 100644 --- a/sel-blocksTests/function.html +++ b/sel-blocksTests/function.html @@ -83,7 +83,7 @@ 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}" + "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} super=user" From 9df5a973e7043a9e5b21c36ae4a0773934e2bbef Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 19:26:49 -0500 Subject: [PATCH 073/116] update doScript, since it's an alias to doFunction doScript now passes the second argument from the command row to doFunction. Without passing this empty string, an error is thrown. With this argument available, scripts could have defined parameters like functions do... but they're the same thing really so... --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index fd90bb1..1dc4ed5 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1385,11 +1385,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); From 1fdc86c30d42a339b8b8ed6f7cb258b6bcdf55ec Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 19:44:16 -0500 Subject: [PATCH 074/116] parameters must be named to be scoped --- sel-blocksTests/try - bubble out of nested function calls.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sel-blocksTests/try - bubble out of nested function calls.html b/sel-blocksTests/try - bubble out of nested function calls.html index f11aa4e..bd12a70 100644 --- a/sel-blocksTests/try - bubble out of nested function calls.html +++ b/sel-blocksTests/try - bubble out of nested function calls.html @@ -91,7 +91,7 @@ function subBub - + n @@ -175,7 +175,6 @@ "([/~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~/])" - From e47b197e2e4c21095ca4b92f9bfb672858a1c942 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 20:02:09 -0500 Subject: [PATCH 075/116] currentCommand should not be overridden This function just marks the status of the current row in the IDE. It should follow the debug index and be called normally. I thought it was doing something else earlier. --- .../chrome/content/extensions/selblocks.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 1dc4ed5..ffda20b 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -325,15 +325,6 @@ function $X(xpath, contextNode, resultType) { " Cannot branch to non-existent command " + String(cachedCommandsData.activeCaseTitle) + " @" + (cmdIdx+1)); branchIdx = cmdIdx; } - function currentCommand () { - var theCase = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)]; - var theIndex = cachedCommandsData.commandIndex; - var command = theCase.commands[theIndex]; - if (!command) { - testCase.log.warn("currentCommand() not found: commands.length=" + theCase.commands.length + ", debugIndex=" + theIndex); - } - return command; - } // Selenium calls reset(): // * before each single (double-click) command execution // * before a testcase is run @@ -357,7 +348,6 @@ function $X(xpath, contextNode, resultType) { // 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); - $$.fn.interceptReplace(testCase.debugContext, "currentCommand", currentCommand); }); // get the blockStack for the currently active callStack From 3b15b1781e121efacfae0f928cde7cf0274982cc Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Fri, 2 Jan 2015 20:25:49 -0500 Subject: [PATCH 076/116] tests that "store" is not block scoped Store adds any var you want to the storedVariables object. The only properties that will be reverted / deleted after function calls are the explicitly named parameters of the function. --- sel-blocksTests/GlobalFunctionsTestSuite.html | 1 + .../function - store not block scoped.html | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 sel-blocksTests/function - store not block scoped.html diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index 8a15ec9..bd2b0dd 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -14,6 +14,7 @@ CallGlobalFunction DefineFunctionParameters - Base DefineFunctionParameters - With Default Values +function - store not block scoped diff --git a/sel-blocksTests/function - store not block scoped.html b/sel-blocksTests/function - store not block scoped.html new file mode 100644 index 0000000..dae0d86 --- /dev/null +++ b/sel-blocksTests/function - store not block scoped.html @@ -0,0 +1,52 @@ + + + + + + +function - store not block scoped + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
function - store not block scoped
functionnoBlockScopescoped
storeI will escape the blockabsconder
storeI will not escape the blockscoped
endFunction
callnoBlockScopescoped="original"
assertEvalstoredVars.scoped === undefinedtrue
assertEvalstoredVars.absconder === "I will escape the block"true
+ + From 49bf74aae470822899565752ca2078d10919da6f Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 14:11:04 -0500 Subject: [PATCH 077/116] Create basic test for SetLocal Adding a new selenium command "SetLocal" to set variables that will be discarded when the block completes. --- sel-blocksTests/GlobalFunctionsTestSuite.html | 1 + sel-blocksTests/StoreLocal - Base.html | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 sel-blocksTests/StoreLocal - Base.html diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index bd2b0dd..e30c20d 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -15,6 +15,7 @@ DefineFunctionParameters - Base DefineFunctionParameters - With Default Values function - store not block scoped +StoreLocal - Base 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
+ + From baf71da3a8a44c94d33d6f6fe6a6360e9e07cb6e Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 16:17:02 -0500 Subject: [PATCH 078/116] Adds local storage fns and ContextManager Local storage is implemented through the ContextManager. Currently it does not enter and exit contexts though, so nothing would appear to change... unless I've got a typo in the code or forgot to wire blockVars, storedVars, and _oStoredVars in... Just checking in the new additions mostly. --- .../chrome/content/extensions/selblocks.js | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index ffda20b..7db5c3f 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -162,6 +162,44 @@ function $X(xpath, contextNode, resultType) { 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 _oStoredVars, blockVars, contextManager; // makes block scoped variables work + + /** + * Manages variable scope for functions, blocks, etc. + * @class ContextManager + */ + function ContextManager() { + _oStoredVars = storedVars; + this.contexts = []; + this.enter(); + } + /** + * Enters a new variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.enter = function enterContext() { + var context = { + here : Object.create(storedVars), + back : storedVars + }; + this.contexts.push(context); + storedVars = context.here; + blockVars = 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; + blockVars = context.back; + } else { + throw new Error("No context to exit from"); + } + }; + contextManager = new ContextManager(); /** * State information about the cache. * currentCaseTitle is the current case displayed in the UI @@ -648,7 +686,33 @@ function $X(xpath, contextNode, resultType) { notifyFatal("Invalid character(s) in " + desc + " name: '" + name + "'"); } } + + Selenium.prototype.doStore = function(value, varName) { + _oStoredVars[varName] = value; + }; + + Selenium.prototype.doStoreText = function(target, varName) { + var element = this.page().findElement(target); + _oStoredVars[varName] = getText(element); + }; + Selenium.prototype.doStoreAttribute = function(target, varName) { + _oStoredVars[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreLocal = function(value, varName) { + blockVars[varName] = value; + }; + + Selenium.prototype.doStoreLocalText = function(target, varName) { + var element = this.page().findElement(target); + blockVars[varName] = getText(element); + }; + + Selenium.prototype.doStoreLocalAttribute = function(target, varName) { + blockVars[varName] = this.page().findAttribute(target); + }; + Selenium.prototype.doLabel = function() { // noop }; From 6c5ed81bbff51a543e4b67013edc79516a764be1 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 17:54:53 -0500 Subject: [PATCH 079/116] Updates tests --- sel-blocksTests/GlobalFunctionsTestSuite.html | 4 +- .../Store - Behaves as StoreLocal.html | 102 ++++++++++++++++++ .../StoreGlobal - Function Scope.html | 89 +++++++++++++++ .../StoreLocal - Function Scope.html | 101 +++++++++++++++++ 4 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 sel-blocksTests/Store - Behaves as StoreLocal.html create mode 100644 sel-blocksTests/StoreGlobal - Function Scope.html create mode 100644 sel-blocksTests/StoreLocal - Function Scope.html diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index e30c20d..8da9fe0 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -15,7 +15,9 @@ DefineFunctionParameters - Base DefineFunctionParameters - With Default Values function - store not block scoped -StoreLocal - Base +StoreLocal - Function Scope +StoreGlobal - Function Scope +Store - Behaves as StoreLocal diff --git a/sel-blocksTests/Store - Behaves as StoreLocal.html b/sel-blocksTests/Store - Behaves as StoreLocal.html new file mode 100644 index 0000000..5607932 --- /dev/null +++ b/sel-blocksTests/Store - Behaves as StoreLocal.html @@ -0,0 +1,102 @@ + + + + + + +Store - Behaves as StoreLocal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store - Behaves as StoreLocal
functionblockScopeVars
storethis is stored locallyl
assertEval_oStoredVars.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalblockVars.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEval_oStoredVars.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l = null;null
assertEval_oStoredVars.l = null;null
callblockScopeVars
assertEval_oStoredVars.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalblockVars.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + diff --git a/sel-blocksTests/StoreGlobal - Function Scope.html b/sel-blocksTests/StoreGlobal - Function Scope.html new file mode 100644 index 0000000..eba628a --- /dev/null +++ b/sel-blocksTests/StoreGlobal - Function Scope.html @@ -0,0 +1,89 @@ + + + + + + +StoreGlobal - Function Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - Function Scope
functionblockScopeVars
storeGlobalthis is stored globallyg
assertEval_oStoredVars.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalblockVars.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endFunction
getEval_oStoredVars.g = null;
assertEval_oStoredVars.g = null;null
callblockScopeVars
assertEval_oStoredVars.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalblockVars.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + diff --git a/sel-blocksTests/StoreLocal - Function Scope.html b/sel-blocksTests/StoreLocal - Function Scope.html new file mode 100644 index 0000000..09ef6e6 --- /dev/null +++ b/sel-blocksTests/StoreLocal - Function Scope.html @@ -0,0 +1,101 @@ + + + + + + +StoreLocal - Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storeLocalthis is stored locallyl
assertEval_oStoredVars.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalblockVars.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEval_oStoredVars.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l = null;null
assertEval_oStoredVars.l = null;null
callblockScopeVars
assertEval_oStoredVars.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalblockVars.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + From d4322412ebb78c4073a26b1fa797ea781ad8b7fb Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 18:00:46 -0500 Subject: [PATCH 080/116] storeLocal and storeGlobal work, funcs have blocks I've implemented block scope for function variables. storeLocal stores local to the block, storeGlobal stores to the global variables. Both local and global variables can be expanded when using the ${} notation. The original store commands, or anything that tries to write directly to storedVars will be subject to the new block scope mechanism. To start a new block scope just write "contextManager.enter()", to return to the parent block scope just write "contextManager.exit()" They should be able to nest for as long and large as a javascript prototype chain is allowed to be. --- .../chrome/content/extensions/selblocks.js | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 7db5c3f..6b0c602 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -162,14 +162,17 @@ function $X(xpath, contextNode, resultType) { 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 _oStoredVars, blockVars, contextManager; // makes block scoped variables work + var contextManager; // makes block scoped variables work /** * Manages variable scope for functions, blocks, etc. * @class ContextManager */ function ContextManager() { + // intentionally global var _oStoredVars = storedVars; + // intentionally global var + blockVars = Object.create(storedVars); this.contexts = []; this.enter(); } @@ -687,32 +690,6 @@ function $X(xpath, contextNode, resultType) { } } - Selenium.prototype.doStore = function(value, varName) { - _oStoredVars[varName] = value; - }; - - Selenium.prototype.doStoreText = function(target, varName) { - var element = this.page().findElement(target); - _oStoredVars[varName] = getText(element); - }; - - Selenium.prototype.doStoreAttribute = function(target, varName) { - _oStoredVars[varName] = this.page().findAttribute(target); - }; - - Selenium.prototype.doStoreLocal = function(value, varName) { - blockVars[varName] = value; - }; - - Selenium.prototype.doStoreLocalText = function(target, varName) { - var element = this.page().findElement(target); - blockVars[varName] = getText(element); - }; - - Selenium.prototype.doStoreLocalAttribute = function(target, varName) { - blockVars[varName] = this.page().findAttribute(target); - }; - Selenium.prototype.doLabel = function() { // noop }; @@ -1404,9 +1381,11 @@ function $X(xpath, contextNode, resultType) { if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); - restoreVarState(callStack.pop().savedVars); + //restoreVarState(callStack.pop().savedVars); + contextManager.exit(); } else { + contextManager.enter(); // pass supplied args to the function call through the call stack var args = parseArgs(argSpec); // saved vars will be populated by the function call @@ -1487,7 +1466,33 @@ function $X(xpath, contextNode, resultType) { // ========= storedVars management ========= + + Selenium.prototype.doStoreGlobal = function(value, varName) { + _oStoredVars[varName] = value; + }; + + Selenium.prototype.doStoreGlobalText = function(target, varName) { + var element = this.page().findElement(target); + _oStoredVars[varName] = getText(element); + }; + Selenium.prototype.doStoreGlobalAttribute = function(target, varName) { + _oStoredVars[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreLocal = function(value, varName) { + blockVars[varName] = value; + }; + + Selenium.prototype.doStoreLocalText = function(target, varName) { + var element = this.page().findElement(target); + blockVars[varName] = getText(element); + }; + + Selenium.prototype.doStoreLocalAttribute = function(target, varName) { + blockVars[varName] = this.page().findAttribute(target); + }; + function evalWithVars(expr) { var result = null; try { From 0062cc976a5dd1874f5ee86e0734bd7f50a74db7 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 19:24:16 -0500 Subject: [PATCH 081/116] can't override doStore for some stupid reason you can't change the store methods on the selenium prototype. Probably because they're cut and pasted over and over and over all over the IDE codebase and reloaded from who knows where, who knows when... --- .../chrome/content/extensions/selblocks.js | 24 ++--- sel-blocksTests/GlobalFunctionsTestSuite.html | 1 + .../Store - Behaves as StoreGlobal.html | 90 +++++++++++++++++++ .../Store - Behaves as StoreLocal.html | 12 +-- .../StoreGlobal - Function Scope.html | 12 +-- .../StoreLocal - Function Scope.html | 12 +-- 6 files changed, 123 insertions(+), 28 deletions(-) create mode 100644 sel-blocksTests/Store - Behaves as StoreGlobal.html diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 6b0c602..e336727 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -170,9 +170,9 @@ function $X(xpath, contextNode, resultType) { */ function ContextManager() { // intentionally global var - _oStoredVars = storedVars; + storedVarsGlobal = storedVars; // intentionally global var - blockVars = Object.create(storedVars); + storedVarsLocal = Object.create(storedVars); this.contexts = []; this.enter(); } @@ -187,7 +187,7 @@ function $X(xpath, contextNode, resultType) { }; this.contexts.push(context); storedVars = context.here; - blockVars = context.here; + storedVarsLocal = context.here; }; /** * Exits to the previous variable context. @@ -197,7 +197,7 @@ function $X(xpath, contextNode, resultType) { if (this.contexts.length > 0) { var context = this.contexts.pop(); storedVars = context.back; - blockVars = context.back; + storedVarsLocal = context.back; } else { throw new Error("No context to exit from"); } @@ -1468,29 +1468,33 @@ function $X(xpath, contextNode, resultType) { // ========= storedVars management ========= Selenium.prototype.doStoreGlobal = function(value, varName) { - _oStoredVars[varName] = value; + storedVarsGlobal[varName] = value; }; Selenium.prototype.doStoreGlobalText = function(target, varName) { var element = this.page().findElement(target); - _oStoredVars[varName] = getText(element); + storedVarsGlobal[varName] = getText(element); }; Selenium.prototype.doStoreGlobalAttribute = function(target, varName) { - _oStoredVars[varName] = this.page().findAttribute(target); + storedVarsGlobal[varName] = this.page().findAttribute(target); }; + Selenium.prototype.doStore = Selenium.prototype.doStoreGlobal; + Selenium.prototype.doStoreText = Selenium.prototype.doStoreGlobalText; + Selenium.prototype.doStoreAttribute = Selenium.prototype.doStoreGlobalAttribute; + Selenium.prototype.doStoreLocal = function(value, varName) { - blockVars[varName] = value; + storedVarsLocal[varName] = value; }; Selenium.prototype.doStoreLocalText = function(target, varName) { var element = this.page().findElement(target); - blockVars[varName] = getText(element); + storedVarsLocal[varName] = getText(element); }; Selenium.prototype.doStoreLocalAttribute = function(target, varName) { - blockVars[varName] = this.page().findAttribute(target); + storedVarsLocal[varName] = this.page().findAttribute(target); }; function evalWithVars(expr) { diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index 8da9fe0..8bd2980 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -18,6 +18,7 @@ StoreLocal - Function Scope StoreGlobal - Function Scope Store - Behaves as StoreLocal +Store - Behaves as StoreGlobal diff --git a/sel-blocksTests/Store - Behaves as StoreGlobal.html b/sel-blocksTests/Store - Behaves as StoreGlobal.html new file mode 100644 index 0000000..1b8de1c --- /dev/null +++ b/sel-blocksTests/Store - Behaves as StoreGlobal.html @@ -0,0 +1,90 @@ + + + + + + +Store - Behaves as StoreGlobal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store - Behaves as StoreGlobal
functionblockScopeVars
storethis 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;null
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/Store - Behaves as StoreLocal.html b/sel-blocksTests/Store - Behaves as StoreLocal.html index 5607932..12905a4 100644 --- a/sel-blocksTests/Store - Behaves as StoreLocal.html +++ b/sel-blocksTests/Store - Behaves as StoreLocal.html @@ -25,7 +25,7 @@ assertEval - _oStoredVars.l === "this is stored locally" + storedVarsGlobal.l === "this is stored locally" false @@ -37,7 +37,7 @@ assertEval - blockVars.l === "this is stored locally" + storedVarsLocal.l === "this is stored locally" true @@ -53,7 +53,7 @@ getEval - _oStoredVars.l = null; + storedVarsGlobal.l = null; @@ -68,7 +68,7 @@ assertEval - _oStoredVars.l = null; + storedVarsGlobal.l = null; null @@ -78,7 +78,7 @@ assertEval - _oStoredVars.l === "this is stored locally" + storedVarsGlobal.l === "this is stored locally" false @@ -88,7 +88,7 @@ assertEval - blockVars.l === "this is stored locally" + storedVarsLocal.l === "this is stored locally" false diff --git a/sel-blocksTests/StoreGlobal - Function Scope.html b/sel-blocksTests/StoreGlobal - Function Scope.html index eba628a..b092889 100644 --- a/sel-blocksTests/StoreGlobal - Function Scope.html +++ b/sel-blocksTests/StoreGlobal - Function Scope.html @@ -25,7 +25,7 @@ assertEval - _oStoredVars.g === "this is stored globally" + storedVarsGlobal.g === "this is stored globally" true @@ -35,7 +35,7 @@ assertEval - blockVars.g === "this is stored globally" + storedVarsLocal.g === "this is stored globally" true @@ -51,12 +51,12 @@ getEval - _oStoredVars.g = null; + storedVarsGlobal.g = null; assertEval - _oStoredVars.g = null; + storedVarsGlobal.g = null; null @@ -66,7 +66,7 @@ assertEval - _oStoredVars.g === "this is stored globally" + storedVarsGlobal.g === "this is stored globally" true @@ -76,7 +76,7 @@ assertEval - blockVars.g === "this is stored globally" + storedVarsLocal.g === "this is stored globally" true diff --git a/sel-blocksTests/StoreLocal - Function Scope.html b/sel-blocksTests/StoreLocal - Function Scope.html index 09ef6e6..3873cde 100644 --- a/sel-blocksTests/StoreLocal - Function Scope.html +++ b/sel-blocksTests/StoreLocal - Function Scope.html @@ -25,7 +25,7 @@ assertEval - _oStoredVars.l === "this is stored locally" + storedVarsGlobal.l === "this is stored locally" false @@ -37,7 +37,7 @@ assertEval - blockVars.l === "this is stored locally" + storedVarsLocal.l === "this is stored locally" true @@ -53,7 +53,7 @@ getEval - _oStoredVars.l = null; + storedVarsGlobal.l = null; @@ -68,7 +68,7 @@ assertEval - _oStoredVars.l = null; + storedVarsGlobal.l = null; null @@ -78,7 +78,7 @@ assertEval - _oStoredVars.l === "this is stored locally" + storedVarsGlobal.l === "this is stored locally" false @@ -88,7 +88,7 @@ assertEval - blockVars.l === "this is stored locally" + storedVarsLocal.l === "this is stored locally" false From e267e437087e2a431eb124eb7f5803b4eeccd5cd Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 21:11:44 -0500 Subject: [PATCH 082/116] fuck it --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index e336727..485c4e7 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1480,10 +1480,6 @@ function $X(xpath, contextNode, resultType) { storedVarsGlobal[varName] = this.page().findAttribute(target); }; - Selenium.prototype.doStore = Selenium.prototype.doStoreGlobal; - Selenium.prototype.doStoreText = Selenium.prototype.doStoreGlobalText; - Selenium.prototype.doStoreAttribute = Selenium.prototype.doStoreGlobalAttribute; - Selenium.prototype.doStoreLocal = function(value, varName) { storedVarsLocal[varName] = value; }; From 29d1e89616371758f4b57fa7f4c17852d07eb45a Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 21:19:21 -0500 Subject: [PATCH 083/116] Breaking change: store is block scoped There's no way to make "store" store variables in global scope and implement block scoping at the same time. They're reloading selenium-runner after loading the plugins and refreshing the default definition for doStore before every command is executed. All we'd need to do is point "doStore" at the new "storedVarsGlobal" and things wouldn't break but.. yeah. --- sel-blocksTests/GlobalFunctionsTestSuite.html | 2 - .../Store - Behaves as StoreGlobal.html | 90 ------------------- .../function - store not block scoped.html | 52 ----------- 3 files changed, 144 deletions(-) delete mode 100644 sel-blocksTests/Store - Behaves as StoreGlobal.html delete mode 100644 sel-blocksTests/function - store not block scoped.html diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index 8bd2980..7b2f42d 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -14,11 +14,9 @@ CallGlobalFunction DefineFunctionParameters - Base DefineFunctionParameters - With Default Values -function - store not block scoped StoreLocal - Function Scope StoreGlobal - Function Scope Store - Behaves as StoreLocal -Store - Behaves as StoreGlobal diff --git a/sel-blocksTests/Store - Behaves as StoreGlobal.html b/sel-blocksTests/Store - Behaves as StoreGlobal.html deleted file mode 100644 index 1b8de1c..0000000 --- a/sel-blocksTests/Store - Behaves as StoreGlobal.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - -Store - Behaves as StoreGlobal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Store - Behaves as StoreGlobal
functionblockScopeVars
storethis 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;null
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/function - store not block scoped.html b/sel-blocksTests/function - store not block scoped.html deleted file mode 100644 index dae0d86..0000000 --- a/sel-blocksTests/function - store not block scoped.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - -function - store not block scoped - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function - store not block scoped
functionnoBlockScopescoped
storeI will escape the blockabsconder
storeI will not escape the blockscoped
endFunction
callnoBlockScopescoped="original"
assertEvalstoredVars.scoped === undefinedtrue
assertEvalstoredVars.absconder === "I will escape the block"true
- - From 574d414d632565b4acc071aecc92e904d213164b Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 22:27:54 -0500 Subject: [PATCH 084/116] adds test for function can return value --- .../Function - Can Return Value.html | 41 +++++++++++++++++++ sel-blocksTests/GlobalFunctionsTestSuite.html | 1 + 2 files changed, 42 insertions(+) create mode 100644 sel-blocksTests/Function - Can Return Value.html 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/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index 7b2f42d..51893c9 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -17,6 +17,7 @@ StoreLocal - Function Scope StoreGlobal - Function Scope Store - Behaves as StoreLocal +Function - Can Return Value From ba85c771b705cde74f40d9cfc3c38a5d9cb3a012 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 22:29:25 -0500 Subject: [PATCH 085/116] pops callstack again, fn context trigger change Entering and exiting context in doCall was too early and too late. Moved context change into doFunction and doEndFunction. --- .../chrome/content/extensions/selblocks.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 485c4e7..b099953 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -173,6 +173,7 @@ function $X(xpath, contextNode, resultType) { storedVarsGlobal = storedVars; // intentionally global var storedVarsLocal = Object.create(storedVars); + storedVars = storedVarsLocal; this.contexts = []; this.enter(); } @@ -1381,11 +1382,10 @@ function $X(xpath, contextNode, resultType) { if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); + callStack.pop() //restoreVarState(callStack.pop().savedVars); - contextManager.exit(); } else { - contextManager.enter(); // pass supplied args to the function call through the call stack var args = parseArgs(argSpec); // saved vars will be populated by the function call @@ -1403,10 +1403,12 @@ function $X(xpath, contextNode, resultType) { 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; + //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 @@ -1446,6 +1448,7 @@ function $X(xpath, contextNode, resultType) { // no active call, we're just skipping around a function block } else { + contextManager.exit(); if (returnVal) { storedVars._result = evalWithVars(returnVal); } activeCallFrame.isReturning = true; // jump back to call command From fbab35b91ca30807e31387a4ce61091d1d41f308 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sat, 3 Jan 2015 22:48:27 -0500 Subject: [PATCH 086/116] Refactor function test for local vars selbench stores "emit" in the storedVars. storedVars is actually block scoped now so the emits are wiped out when the function returns. I'm returning the values that were emitted before and asserting their correctness immediately. --- sel-blocksTests/function.html | 83 +++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/sel-blocksTests/function.html b/sel-blocksTests/function.html index a4112c0..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} super=user" + 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 From 3c8175d0ee739961684122d7cb8e91f32b0b28fe Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 03:04:46 -0500 Subject: [PATCH 087/116] adding block scope to loops --- .../chrome/content/extensions/selblocks.js | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index b099953..9c0d3fa 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -163,16 +163,15 @@ function $X(xpath, contextNode, resultType) { 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 - storedVarsGlobal = storedVars; - // intentionally global var - storedVarsLocal = Object.create(storedVars); + storedVarsLocal = Object.create(storedVarsGlobal); storedVars = storedVarsLocal; this.contexts = []; this.enter(); @@ -182,9 +181,10 @@ function $X(xpath, contextNode, resultType) { * @methodOf ContextManager. */ ContextManager.prototype.enter = function enterContext() { + var _o = storedVars; var context = { here : Object.create(storedVars), - back : storedVars + back : _o }; this.contexts.push(context); storedVars = context.here; @@ -203,6 +203,20 @@ function $X(xpath, contextNode, resultType) { throw new Error("No context to exit from"); } }; + /** + * Resets to the top variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.reset = function exitContext() { + if (this.contexts.length > 0) { + storedVars = storedVarsGlobal; + storedVarsLocal = storedVarsGlobal; + this.contexts = []; + this.enter(); + } else { + throw new Error("No context to exit from"); + } + }; contextManager = new ContextManager(); /** * State information about the cache. @@ -376,6 +390,7 @@ function $X(xpath, contextNode, resultType) { { $$.LOG.trace("In tail intercept :: Selenium.reset()"); try { + contextManager.reset(); compileSelBlocks(); } catch (err) { @@ -978,7 +993,8 @@ function $X(xpath, contextNode, resultType) { while (!tryState && $$.tcf.nestingLevel > -1 && callStack.length > 1) { var callFrame = callStack.pop(); $$.LOG.info("function '" + callFrame.name + "' aborting due to error"); - restoreVarState(callFrame.savedVars); + contextManager.exit(); + //restoreVarState(callFrame.savedVars); tryState = unwindToBlock(_hasCriteria); } return tryState; @@ -1290,6 +1306,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); } @@ -1312,7 +1329,8 @@ function $X(xpath, contextNode, resultType) { assertActiveScope(blkDefHere().beginIdx); var loopState = activeBlockStack().top(); if (loopState.isComplete) { - restoreVarState(loopState.savedVars); + contextManager.exit(); + //restoreVarState(loopState.savedVars); activeBlockStack().pop(); // done, fall out of loop } @@ -1547,7 +1565,7 @@ 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; } } } From 2c47b8e51c3ff71c54b56fb3118cf59a31eaeb91 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 10:53:01 -0500 Subject: [PATCH 088/116] improves return, storeEval in scope The built in storeEval makes variables that are local to the block scope. This adds the ability to do the same but in global scope. I had exited the context too early in returns, so variable expansion in return values was broken for a minute. --- .../chrome/content/extensions/selblocks.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 9c0d3fa..10befe1 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1460,14 +1460,16 @@ 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) { ret = evalWithVars(returnVal); } contextManager.exit(); - if (returnVal) { storedVars._result = evalWithVars(returnVal); } + storedVars._result = ret; activeCallFrame.isReturning = true; // jump back to call command cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); @@ -1491,6 +1493,11 @@ function $X(xpath, contextNode, resultType) { 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); @@ -1505,6 +1512,11 @@ function $X(xpath, contextNode, resultType) { 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); From 1e7bcc14dd17b2e3c381a47b6babba4366798bb3 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 11:04:01 -0500 Subject: [PATCH 089/116] update test for block scope The iterator value "w" is evaluated and stored inside the "with" block. The iterator emits the right values but after the block is completed, emitting "end ${w}" gets the value of w in the scope above the "with" block, which hasn't been changed. The variable is automatically shadowed in local scope, so storing the iterator value globally doesn't work because the updated value isn't visible locally. I don't know how that works exactly, it's something with the way arguments are being parsed. --- sel-blocksTests/while.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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" From 38f795b44e60ef9192e9db8bafd5ac01811ebd86 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 11:25:10 -0500 Subject: [PATCH 090/116] update test for block scope the value for i will be the same at the start and end because it's incremented in block scope to the for loops. --- sel-blocksTests/nested-loops.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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" From 22673d089b7fd04ebce52c9ec0d80b9355b0026e Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 12:03:52 -0500 Subject: [PATCH 091/116] bubbles any _result through contexts --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 10befe1..2814aed 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -990,10 +990,13 @@ 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"); + if (storedVars._result) { ret = storedVars._result; } contextManager.exit(); + storedVars._result = ret; //restoreVarState(callFrame.savedVars); tryState = unwindToBlock(_hasCriteria); } @@ -1328,8 +1331,12 @@ function $X(xpath, contextNode, resultType) { 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 From a6dcf55b880d3c898fc85213fa9cc50dd7d32a4a Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 12:06:08 -0500 Subject: [PATCH 092/116] updated test this test is really convoluted. It looks like "finally" is supposed to execute even after a return statement. That finally throws, so nothing is being returned. --- .../try - command bubbling return replaced by error.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sel-blocksTests/try - command bubbling return replaced by error.html b/sel-blocksTests/try - command bubbling return replaced by error.html index 165cd6a..139c160 100644 --- a/sel-blocksTests/try - command bubbling return replaced by error.html +++ b/sel-blocksTests/try - command bubbling return replaced by error.html @@ -147,10 +147,9 @@ assertEmitted - "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned 2~/])" + "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])" - From d0c23167d7199ad5319ab37427be3f4f0dabd0b2 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 12:06:41 -0500 Subject: [PATCH 093/116] Adds tests for while scoping --- sel-blocksTests/GlobalFunctionsTestSuite.html | 2 + .../StoreGlobal - While Scope.html | 96 ++++++++++++++++ sel-blocksTests/StoreLocal - While Scope.html | 108 ++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 sel-blocksTests/StoreGlobal - While Scope.html create mode 100644 sel-blocksTests/StoreLocal - While Scope.html diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index 51893c9..1ace39f 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -16,6 +16,8 @@ DefineFunctionParameters - With Default Values StoreLocal - Function Scope StoreGlobal - Function Scope +StoreGlobal - While Scope +StoreLocal - While Scope Store - Behaves as StoreLocal Function - Can Return Value diff --git a/sel-blocksTests/StoreGlobal - While Scope.html b/sel-blocksTests/StoreGlobal - While Scope.html new file mode 100644 index 0000000..c0b8d30 --- /dev/null +++ b/sel-blocksTests/StoreGlobal - While Scope.html @@ -0,0 +1,96 @@ + + + + + + +StoreGlobal - While Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - While Scope
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g = null;null
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 - While Scope.html b/sel-blocksTests/StoreLocal - While Scope.html new file mode 100644 index 0000000..08012f9 --- /dev/null +++ b/sel-blocksTests/StoreLocal - While Scope.html @@ -0,0 +1,108 @@ + + + + + + +StoreLocal - While Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - While Scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l = null;null
assertEvalstoredVarsGlobal.l = null;null
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
+ + From a9ab71fd566e3ca33af0a80f136604ecd583d878 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 19:03:04 -0500 Subject: [PATCH 094/116] updates getEval on a few tests I was setting and verifying at the same time, which is wrong. --- sel-blocksTests/GlobalFunctionsTestSuite.html | 2 ++ sel-blocksTests/Store - Behaves as StoreLocal.html | 9 ++++----- sel-blocksTests/StoreGlobal - Function Scope.html | 4 ++-- sel-blocksTests/StoreGlobal - While Scope.html | 5 ++--- sel-blocksTests/StoreLocal - Function Scope.html | 8 ++++---- sel-blocksTests/StoreLocal - While Scope.html | 9 ++++----- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html index 1ace39f..c171f0e 100644 --- a/sel-blocksTests/GlobalFunctionsTestSuite.html +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -20,6 +20,8 @@ StoreLocal - While Scope Store - Behaves as StoreLocal Function - Can Return Value +StoreAt - Function Scope Nesting +StoreAt - While Scope Nesting diff --git a/sel-blocksTests/Store - Behaves as StoreLocal.html b/sel-blocksTests/Store - Behaves as StoreLocal.html index 12905a4..a917370 100644 --- a/sel-blocksTests/Store - Behaves as StoreLocal.html +++ b/sel-blocksTests/Store - Behaves as StoreLocal.html @@ -63,13 +63,13 @@ assertEval - storedVars.l = null; - null + storedVars.l === null; + true assertEval - storedVarsGlobal.l = null; - null + storedVarsGlobal.l === null; + true call @@ -96,7 +96,6 @@ "${l}" === "this is stored locally" false - diff --git a/sel-blocksTests/StoreGlobal - Function Scope.html b/sel-blocksTests/StoreGlobal - Function Scope.html index b092889..5c61fc5 100644 --- a/sel-blocksTests/StoreGlobal - Function Scope.html +++ b/sel-blocksTests/StoreGlobal - Function Scope.html @@ -56,8 +56,8 @@ assertEval - storedVarsGlobal.g = null; - null + storedVarsGlobal.g === null; + true call diff --git a/sel-blocksTests/StoreGlobal - While Scope.html b/sel-blocksTests/StoreGlobal - While Scope.html index c0b8d30..80d8560 100644 --- a/sel-blocksTests/StoreGlobal - While Scope.html +++ b/sel-blocksTests/StoreGlobal - While Scope.html @@ -19,8 +19,8 @@ assertEval - storedVarsGlobal.g = null; - null + storedVarsGlobal.g === null; + true store @@ -90,7 +90,6 @@ "${g}" === "this is stored globally" true - diff --git a/sel-blocksTests/StoreLocal - Function Scope.html b/sel-blocksTests/StoreLocal - Function Scope.html index 3873cde..944f809 100644 --- a/sel-blocksTests/StoreLocal - Function Scope.html +++ b/sel-blocksTests/StoreLocal - Function Scope.html @@ -63,13 +63,13 @@ assertEval - storedVars.l = null; - null + storedVars.l === null; + true assertEval - storedVarsGlobal.l = null; - null + storedVarsGlobal.l === null; + true call diff --git a/sel-blocksTests/StoreLocal - While Scope.html b/sel-blocksTests/StoreLocal - While Scope.html index 08012f9..cf71f8f 100644 --- a/sel-blocksTests/StoreLocal - While Scope.html +++ b/sel-blocksTests/StoreLocal - While Scope.html @@ -24,13 +24,13 @@ assertEval - storedVars.l = null; - null + storedVars.l === null; + true assertEval - storedVarsGlobal.l = null; - null + storedVarsGlobal.l === null; + true store @@ -102,7 +102,6 @@ "${l}" === "this is stored locally" false - From b207dac10e65d806a426ff11002f6414db032632 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 19:06:53 -0500 Subject: [PATCH 095/116] adds storeAt command and tests The tests explain it better than I can. Basically, without this you only have the choice of shadowing variables in the child scope, or setting globals all the time to pass data around. storeAt allows you to name a variable defined in any preceeding scope and bubble the value to set on it. The changed value will be available after you exit the current scope, so you can do things like "while" and "for" loops without bouncing return values off the global scope. . . Just storeAt whatever receiving variable you have set up in the parent and it's like magic! --- .../chrome/content/extensions/selblocks.js | 45 ++++++ .../StoreAt - Function Scope Nesting.html | 129 ++++++++++++++++ .../StoreAt - While Scope Nesting.html | 140 ++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 sel-blocksTests/StoreAt - Function Scope Nesting.html create mode 100644 sel-blocksTests/StoreAt - While Scope Nesting.html diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 2814aed..e23f87a 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -217,6 +217,31 @@ function $X(xpath, contextNode, resultType) { throw new Error("No context to exit from"); } }; + /** + * 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. @@ -1533,6 +1558,26 @@ function $X(xpath, contextNode, resultType) { 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 { 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
+ + From 890ea826f7523707a239734a00570cb9ca85ea77 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 22:45:59 -0500 Subject: [PATCH 096/116] updates user extension to latest --- testUserExtension/results-firefox.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testUserExtension/results-firefox.html b/testUserExtension/results-firefox.html index b4a960e..dc8a1b5 100644 --- a/testUserExtension/results-firefox.html +++ b/testUserExtension/results-firefox.html @@ -54,7 +54,7 @@

Test suite results

totalTime: -37 +28 numTestTotal: @@ -6107,7 +6107,7 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 2.205 sec elapsed: +info: [SelBench] 2.275 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 0" | | info: Starting test /selenium-server/tests/function.html info: Executing: |resetEmitted | | | From c025675f03dc64b3a37d5d6874ea091a99fe0027 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 23:09:07 -0500 Subject: [PATCH 097/116] added global functions tests to main suite --- sel-blocksTests/_SelBlocks-TestSuite.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 1794943..f364afb 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -53,6 +53,20 @@ exitTest - base case exitTest - from within a loop exitTest - from within a function +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 From f12aba4dca92650f9b057942af5bfa3e8483d919 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 4 Jan 2015 23:11:03 -0500 Subject: [PATCH 098/116] allowing 3 minutes for default autotesting The new tests might take a little while because the websites might not respond immediately. --- testUserExtension/runTestsOnServer.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testUserExtension/runTestsOnServer.cmd b/testUserExtension/runTestsOnServer.cmd index 542ea23..c9c5951 100644 --- a/testUserExtension/runTestsOnServer.cmd +++ b/testUserExtension/runTestsOnServer.cmd @@ -4,7 +4,7 @@ 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=90 +SET /a autotestTimeoutInSeconds=180 REM the root of the project REM C:\projects\selenium\selblocks\SelBlocks\ SET projectRoot=%~dp0..\ From ec9c0095d97ce3d4cdb6c9c7e54dd26af701bf74 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 5 Jan 2015 00:33:31 -0500 Subject: [PATCH 099/116] cleaning up new tests --- sel-blocksTests/CallGlobalFunction.html | 15 +++++---------- sel-blocksTests/CreateGlobalVars.html | 10 ---------- sel-blocksTests/GlobalFunctions 2.html | 9 ++------- sel-blocksTests/GlobalFunctions.html | 7 +------ 4 files changed, 8 insertions(+), 33 deletions(-) diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html index 5066a9a..d658a24 100644 --- a/sel-blocksTests/CallGlobalFunction.html +++ b/sel-blocksTests/CallGlobalFunction.html @@ -15,16 +15,6 @@ globalStoredVars.aGlobalVar = "reset"; - - getEval - globalStoredVars.aGlobalVar = "reset"; - - - - getEval - globalStoredVars.aGlobalVar = "reset"; - - assertNotEval globalStoredVars.aGlobalVar; @@ -50,6 +40,11 @@ GlobalFunctions 2.doStuff + + assertLocation + http://htmlpreview.github.io/ + + diff --git a/sel-blocksTests/CreateGlobalVars.html b/sel-blocksTests/CreateGlobalVars.html index af27f19..576a829 100644 --- a/sel-blocksTests/CreateGlobalVars.html +++ b/sel-blocksTests/CreateGlobalVars.html @@ -15,16 +15,6 @@ globalStoredVars = {}; - - getEval - globalStoredVars = {}; - - - - getEval - globalStoredVars = {}; - - diff --git a/sel-blocksTests/GlobalFunctions 2.html b/sel-blocksTests/GlobalFunctions 2.html index 80832c9..11780c7 100644 --- a/sel-blocksTests/GlobalFunctions 2.html +++ b/sel-blocksTests/GlobalFunctions 2.html @@ -18,12 +18,7 @@ open - https://github.com/ - - - - open - http://en.wikipedia.org/wiki/Chili + http://htmlpreview.github.io/ @@ -38,7 +33,7 @@ assertLocation - http://en.wikipedia.org/wiki/Chili + http://htmlpreview.github.io/ diff --git a/sel-blocksTests/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html index adcc056..8d83941 100644 --- a/sel-blocksTests/GlobalFunctions.html +++ b/sel-blocksTests/GlobalFunctions.html @@ -17,7 +17,7 @@ open - http://www.google.com + http://htmlpreview.github.io/ @@ -25,11 +25,6 @@ globalStoredVars.aGlobalVar = "set"; - - open - http://www.yahoo.com - - endFunction From bd70032e0590d74aca1016cbf313c4b16182a1dd Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 5 Jan 2015 00:35:10 -0500 Subject: [PATCH 100/116] get title, set highlighted row on server --- .../chrome/content/extensions/selblocks.js | 13 ++++++++++--- user extension/user-extensions.js | 13 ++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index de1a67c..5150100 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -271,7 +271,12 @@ function $X(xpath, contextNode, resultType) { */ init : function cacheInit() { cachedCommandsData.initializing = true; - var _mytitle = testCase.title || "untitiled"; + 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 @@ -394,8 +399,10 @@ function $X(xpath, contextNode, resultType) { if(globalContext.onServer === true) { this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; - command = this.currentRow.getCommand(); - command.type = "command"; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + command = this.currentRow.getCommand(); + command.type = "command"; + } if (this.sejsElement) { this.currentItem = agenda.pop(); this.currentRowIndex = this.debugIndex; diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 9546b0f..9c34378 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -874,7 +874,12 @@ function $X(xpath, contextNode, resultType) { */ init : function cacheInit() { cachedCommandsData.initializing = true; - var _mytitle = testCase.title || "untitiled"; + 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 @@ -997,8 +1002,10 @@ function $X(xpath, contextNode, resultType) { if(globalContext.onServer === true) { this.currentRow = this.htmlTestCase.commandRows[this.debugIndex]; - command = this.currentRow.getCommand(); - command.type = "command"; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + command = this.currentRow.getCommand(); + command.type = "command"; + } if (this.sejsElement) { this.currentItem = agenda.pop(); this.currentRowIndex = this.debugIndex; From 61a5c48437e889160ef6561f51baafda437ff2b1 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 5 Jan 2015 00:41:31 -0500 Subject: [PATCH 101/116] Passes testing in all but IE Everything is working as expected in the IDE, and on the server in Firefox and Chrome. Internet Explorer passes all the tests except for calling functions across cases. I don't know if it's because the functions I'm testing are calling slow web pages or if it's some kind of syntax error in IE when we use the command name "call". IE is cool and all, but I'm submitting this because it works everywhere else and one of us will be able to figure out the bug in IE in the near future. --- IDE test results.html | 2978 +++++++++++++++++-- testUserExtension/results-firefox.html | 1761 ++++++++++- testUserExtension/results-googlechrome.html | 2310 ++++++++++++-- testUserExtension/results-piiexplore.html | 2342 +++++++++++++-- 4 files changed, 8671 insertions(+), 720 deletions(-) diff --git a/IDE test results.html b/IDE test results.html index 3624ee9..60708b3 100644 --- a/IDE test results.html +++ b/IDE test results.html @@ -1,13 +1,29 @@ - - + - - +
Test Suite Results
+ + + + +
Test Suite: _SelBlocks-TestSuite.html
Test cases: 59 total / 58 passed / 1 failed
Commands: 999 total / 915 passed / 1 failed / 83 skipped

+ + + @@ -47,3838 +63,4895 @@ - + + + + + + + + + + + + + + +
Index of test cases
README
eval
branching
continue-break 3
continue-break 4
nested-loops
function
function
function-recursive
issue-2-function
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
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
- + +


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


eval
+ + + + - + + + + + - + + + + + - + + + + + - +
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"
- + +


branching
+ + + + + + + + + + + + + + + + + + - - + + + + + - + + + + + - + + + + + - + +
Test case: branching
resetEmitted
emit "BEFORE"
goto HERE
emit "A"
label HERE
gotoIf true THERE
emit "B"
label THERE
skipNext
emit "C"
emit "AFTER"
assertEmitted "BEFORE~AFTER"
=== Error validations
-!-
expectError "Target label 'NOWHERE' is not found"
goto NOWHERE
-!-
expectError "Target label 'NOWHERE' is not found"
gotoIf true NOWHERE
-!-
expectError "Requires a number > 1"
skipNext -1
-!-
expectError /.*random.* (is not |is un)defined/
skipNext random
- + +


if-1
+ + + + + - + + + + + + - + + + + + + - + + + + + + + + - + + + + + + + + - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + - +
Test case: if-1
resetEmitted
emit "BEFORE"
--
if true
emit "truthy"
endIf
--
if false
emit "falsey"
endIf
--
if true
emit "A"
else
emit "B"
endIf
--
if false
emit "X"
else
emit "Y"
endIf
--
if false
emit "false teeth"
else
if true
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"
- + +


if-2
+ + + + - + + + + + + + + - + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + - + + + + + + + +
Test case: if-2
resetEmitted
==
if true
emit "if-y"
elseIf true
emit "elseIf-y"
endIf
--
if false
emit "if-y"
elseIf true
emit "elseIf-y"
endIf
--
if false
emit "if-y"
elseIf true
emit "elseIf-a1y"
elseIf true
emit "else-a2y"
endIf
--
if false
emit "if-y"
elseIf false
emit "elseIf-b1y"
elseIf true
emit "elseIf-b2y"
endIf
--
if false
emit "if-y"
elseIf false
emit "elseIf-y"
else
emit "else-y"
endIf
assertEmitted "if-y~elseIf-y~elseIf-a1y~elseIf-b2y~else-y"
- + +


if-3
+ + + + - + + + + + + + + + + + + + +
Test case: if-3
resetEmitted
--
foreach i 2, 0, 1, 4, 3, 5
if i == 0
emit "if-${i}"
elseIf i == 1
emit "elseIf-${i}"
elseIf i == 2
emit "elseIf-${i}"
elseIf i == 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
+ + + + + + + - + + + + + + - + + +
Test case: try - noop
log "-- no-op try --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try t-noop
emit "trying"
endTry t-noop
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying~/])"
- + +


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


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


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


try - catch specific error then finally
+ + + + + + + - + + + + + + + - + + + + + + + + + + + + - + + + + + + - + + +
Test case: try - catch specific error then finally
log "-- catch specific error, then finally --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try t-spec-outer
emit "trying outer"
assertEval selblocks.tcf.nestingLevel -1
emit "([/"
v v v
try t-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"
endTry t-spec-inner
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
endTry t-spec-outer
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])"
- + +


try - catch throw finally throw
+ + + + + + + - + + + + - + + + + + + + + + + + + + + + + + + - + + + + + + + - + + +
Test case: try - catch throw finally throw
log "-- catch/throw, finally/throw --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try tcf-trap
v v v
assertEval selblocks.tcf.nestingLevel 0
try tcf
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
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel 0
catch
emit "caught '" + _error.message + "'"
endTry
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])"
- + +


try - bubble up to catch ALL
+ + + + + + + - + + + + + + - + + + + + + + + + + - + + + + + + + - + + +
Test case: try - bubble up to catch ALL
log "-- bubble up to catch ALL --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try t-all-outer
emit "trying-outer"
assertEval selblocks.tcf.nestingLevel 0
v v v
try t-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 + "'"
endTry t-all-inner
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel 0
catch
emit "caught-outer '" + _error.message + "'"
endTry t-all-outer
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])"
- + +


try - bubble up to catch ALL via finally
+ + + + + + + - + + + + + + - + + + + + + + + + + + + - + + + + + + + - + + +
Test case: try - bubble up to catch ALL via finally
log "-- bubble up to catch ALL via finally --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try t-allfin-outer
emit "trying-outer"
assertEval selblocks.tcf.nestingLevel 0
v v v
try t-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"
endTry t-allfin-inner
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel 0
catch
emit "caught-outer '" + _error.message + "'"
endTry t-allfin-outer
^ ^ ^ ^
assertEval selblocks.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
+ + + + + + + - + + + + + + - + + + + + + + + + + - + + + + + + + + - + + +
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 "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try noop-outer
emit "trying outer"
assertEval selblocks.tcf.nestingLevel 0
v v v
try op-inner
emit "trying inner"
assertEval selblocks.tcf.nestingLevel 1
emit "throwing inner"
throw "blamo"
assertEval "this command should not be reached, due to throw"
endTry op-inner
^ ^ ^ ^
catch /blamo/
emit "caught '" + _error.message + "'"
finally
emit "finally"
endTry noop-outer
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])"
- + +


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


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


try - throw catch rethrow
+ + + + + + + - + + + + + + - + + + + + + + + + + + + + + - + + + + + + - + + +
Test case: try - throw catch rethrow
log "-- throw, catch, rethrow --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try outer
emit "trying outer"
assertEval selblocks.tcf.nestingLevel 0
v v v
try inner
emit "trying inner"
assertEval selblocks.tcf.nestingLevel 1
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"
endTry inner
^ ^ ^ ^
catch /blamo2/
emit "caught '" + _error.message + "'"
endTry outer
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])"
- + +


try - bubble out of nested function calls
+ + + + + + + - + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + - + + + +
Test case: try - bubble out of nested function calls
log "-- bubble out of nested function calls --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try bub-invoke
emit "trying"
emit "calling"
call subBub n = 0
assertEval "this command should not be reached, due error thrown in function"
catch /blamo/
emit "caught '" + _error.message + "'"
finally
emit "finally"
endTry bub-invoke
assertEval selblocks.tcf.nestingLevel -1
^ ^ ^ ^
function subBubn
v v v
try tcf-inner
emit "${n}) trying-inner"
if n < 2
emit "${n}) calling"
call subBub n = n+1
else
emit "${n}) throwing"
throw "blamo"
endIf
finally
emit "${n}) finally"
endTry tcf-inner
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel 0
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
+ + + + + + + + + - + + + + + + + + + + + + - + + + + +
Test case: try - command bubbling break with finally
log "-- command bubbling, break w/finally --"
resetEmitted
emit "([/"
emit "while'g"
for w=3; w > 0; w--
assertEval selblocks.tcf.nestingLevel -1
v v v
try breaker
emit "${w}) trying"
if w==2
emit "${w}) BREAK"
break
endIf
finally
emit "${w}) finallying"
endTry breaker
^ ^ ^ ^
assertEval selblocks.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
+ + + + + + + - + + + + + + + + + + + + + + + + - + + +
Test case: try - command bubbling intra try break
log "-- command bubbling, intra-try break --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try breaker
emit "trying"
emit "while'g"
for w=3; w > 0; w--
if w==2
emit "${w}) BREAK"
break
endIf
emit "${w}) iterating"
endFor
finally
emit "finallying"
endTry breaker
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying~while'g~3) iterating~2) BREAK~finallying~/])"
- + +


try - command bubbling continue with finally
+ + + + + + + + + - + + + + + + + + + + + + - + + + + +
Test case: try - command bubbling continue with finally
log "-- command bubbling, continue w/finally --"
resetEmitted
emit "([/"
emit "while'g"
for w=3; w > 0; w--
assertEval selblocks.tcf.nestingLevel -1
v v v
try continuer
emit "${w}) trying"
if w==2
emit "${w}) CONTINUE"
continue
endIf
finally
emit "${w}) finallying"
endTry continuer
^ ^ ^ ^
assertEval selblocks.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
+ + + + + + + - + + + + + + + + + + + + + + + + - + + +
Test case: try - command bubbling intra try continue
log "-- command bubbling, intra-try continue --"
resetEmitted
emit "([/"
assertEval selblocks.tcf.nestingLevel -1
v v v
try continuer
emit "trying"
emit "while'g"
for w=3; w > 0; w--
if w==2
emit "${w}) CONTINUE"
continue
endIf
emit "${w}) iterating"
endFor
finally
emit "finallying"
endTry continuer
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "/])"
assertEmitted "([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])"
- + +


try - command bubbling error replaced by return
+ + + + + + + + + + + + - + + + + + + + + + + + + - + + + +
Test case: try - command bubbling error replaced by return
log "-- command bubbling, error replaced by return --"
resetEmitted
emit "([/"
emit "calling"
call cmdBubA
emit "returned ${_result}"
function cmdBubA
emit "in cmdBubA"
assertEval selblocks.tcf.nestingLevel -1
v v v
try cmdBub-tcf
emit "trying"
emit "returning (1)"
return 1
finally
emit "finallying"
emit "returning (2)"
return 2
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
+ + + + + + + + + + + + - + + + + + + + + + + + + - + + + +
Test case: try - command bubbling error replaced by return 2
log "-- command bubbling, error replaced by return --"
resetEmitted
emit "([/"
emit "calling"
call cmdBubB
emit "returned ${_result}"
function cmdBubB
emit "in cmdBubB"
assertEval selblocks.tcf.nestingLevel -1
v v v
try cmdBub-tcf
emit "trying"
emit "throwing"
throw "short-lived error"
finally
emit "finallying"
emit "returning (2)"
return 2
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
+ + + + + + + + + + + + - + + + + + - + + + + + + + + + + + + - + + + + + + + - + + - + +
Test case: try - command bubbling return replaced by error
log "-- command bubbling, return replaced by error --"
resetEmitted
emit "([/"
emit "calling"
call cmdBubC
emit "returned ${_result}"
function cmdBubC
emit "in cmdBubC"
assertEval selblocks.tcf.nestingLevel -1
v v v
try cmdBub-tcf-guardrail
assertEval selblocks.tcf.nestingLevel 0
v v v
try cmdBub-tcf
emit "trying"
emit "returning (1)"
return 1
finally
emit "finallying"
emit "throwing"
throw "this-error-replaces-return-1"
endTry
^ ^ ^ ^
catch /this-error-replaces-return-1/
emit "caught '" + _error.message + "'"
assertEval selblocks.tcf.nestingLevel 0
endTry
^ ^ ^ ^
endFunction
emit "/])"
assertEmitted"([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned 2~/])""([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])"
- + +


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


try - try without matching catch
+ + + + + + - + + + + + + + + + + + + - + +
Test case: try - try without matching catch
log "-- try without matching catch --"
resetEmitted
assertEval selblocks.tcf.nestingLevel -1
v v v
try miss
assertEval true true
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"
endTry miss 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
^ ^ ^ ^
assertEval selblocks.tcf.nestingLevel -1
emit "trying"
- + +


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


for
+ + + + + + + + + + - +
Test case: for
resetEmitted
deleteVars f
emit "START ${f}"
for s=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}"
- + +


foreach
+ + + + + + + + + + - +
Test case: foreach
resetEmitted
deleteVars _i, fe
emit "START ${_i}-${fe}"
foreach fe "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}"
- + +


foreach-xpath
+ + + + + + + + + + +
Test case: foreach-xpath
resetEmitted
echo $x("//input")
echo $X("//input")
echo begin
emit "START ${_i}) ${link}"
foreach link $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}"
- + +


forjson
+ + + + + + + + + + + - + + + + + + + - + + + + + - + + + + + + + - - + + + + + - + + + + + - + +
Test case: forjson
if globalContext.onServer === true
store ../data/forjson.json forJsonFileName
else
store data/forjson.json forJsonFileName
endIf
resetEmitted
deleteVars jname
emit "START ${jname}"
--- forJson
forJson ${forJsonFileName}
emit jname
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"
- + +


forxml
+ + + + + + + + + + + - + + + + + + + - + + + + + - + + + + + + + + - - + + + + + - + + + + + - + +
Test case: forxml
if globalContext.onServer === true
store ../data/forxml.xml forXmlFileName
else
store data/forxml.xml forXmlFileName
endIf
resetEmitted
deleteVars xname
emit "START ${xname}"
--- forXml
forXml ${forXmlFileName}
emit xname
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"
- + +


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


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


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


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


nested-loops
+ + + + + + + + + + + + + + + + + + + + + + + + - - + +
Test case: nested-loops
resetEmitted
deleteVars i, n, uname
startTimer
store 2 i
emit "START ${i}"
while i > 0
emit "while=${i}"
foreach uname "dilbert", "dogbert"
emit "foreach=${uname}"
for n = 2; n <=3; n++
emit "FOR=${n}"
for n = 7; n <= 8; n++
emit "for=${n}"
endFor
endFor
emit "endFor ${n}"
endForeach
storeEval ${i}-1 i
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 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"
- - - - - - + +


function
resetEmitted
+ - - - + + + + - + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + + - - + + + - - - - + + + + - - + + + + + + + + + + + - - + + @@ -3886,310 +4959,1819 @@ + - + + + + + + + + + + - - + + +
Test case: function
deleteVars sname, srole
emit"START ${sname} ${srole}"
assertEval"START ${sname} ${srole}" === "START ${commands}quot; + "{sname} ${commands}quot; + "{srole}"true
--- first line
call doSomething sname = "dilbert,Q", srole = "goof"
assertEval"${_result}" === "sname=dilbert,Q,srole=goof"true
deleteVarssname, srole
===
function doSomething sname
emitreturn "sname=${sname},srole=${srole}"
endFunction doSomething
===
deleteVarssname, srole
call doSomething sname = "dogbert", srole = "woof"
assertEval"${_result}" === "sname=dogbert,srole=woof"true
deleteVarssname, srole
call doSomething sname = "ratbert", srole = "squeak"
assertEval"${_result}" === "sname=ratbert,srole=squeak"true
deleteVarssname, srole
---
foreach sname "asok", "alice"
call doSomething sname = sname, srole = "super=user"
assertEval"${_result}" === "sname=${sname},srole=super=user"true
endForeachdeleteVarssname, srole
emit"DONE ${sname} ${srole}"endForeach
assertEmitted"START ${commands}quot; + "{sname} ${commands}quot; + "{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 ${commands}quot; + "{sname} ${commands}quot; + "{srole}"
assertEval"DONE ${sname} ${srole}" === "DONE ${commands}quot; + "{sname} ${commands}quot; + "{srole}"true
=== Error validations
-!-
expectError "Function does not exist: NONEXISTENT"
call NONEXISTENT
=== deprecated script commands
resetEmitteddeleteVarssname, srole
script doDeprecated sname
emitreturn "sname=${sname},srole=${srole}"
endScript doDeprecated
call doDeprecated sname = "wally", srole = "lazy"
assertEval"${_result}" === "sname=wally,srole=lazy"true
assertEmitted"sname=wally,srole=lazy"deleteVarssname, srole
- + +


function-recursive
+ + + + + + + + + + + + + - - + + + + + + + + + + + + + + + - - + + + + + + + + + + - + + + + + + + + + + - + + + + + - +
Test case: function-recursive
resetEmitted
deleteVars degree, n, _result, ud
store 7 degree
startTimer factorial ${degree}
call fac n=degree
timerElapsed
emit degree + "!=" + _result
===
--- recursive factorial
function fac n
if n <= 1
return 1
else
call fac n = n-1
emit _result
return n * _result
endIf
endFunction
===
--- mutual recursive
function uno
emit "UNO"
storeEval ${ud}-1 ud
if ud > 0
call due
endIf
endFunction uno
---
function due
emit "DUE"
storeEval ${ud}-1 ud
if ud > 0
call uno
endIf
endFunction due
---
store 5 ud
call uno
===
assertEmitted "1~2~6~24~120~720~7!=5040~UNO~DUE~UNO~DUE~UNO"
- + +


issue-2-function
+ + + +
Test case: issue-2-function
function xyz
log 'here'
endFunction
call xyz
- + +


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


exitTest - from within a loop
+ + + + + + + + + +
Test case: exitTest - from within a loop
-- from within a loop
for i=0; i < 5; i++
if i == 3
exitTest
endIf
if i === 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
+ + + + + + + + + + +
Test case: exitTest - from within a function
-- from within a function
call doSubExit
throw "shouldn't happen"
function doSubExit
exitTest
endFunction doSubExit
+ +


+ + + + + + +
Test case: CreateGlobalVars
getEvalglobalStoredVars = {};
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: GlobalFunctions
functionsetGlobalVar
openhttp://htmlpreview.github.io/
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test case: CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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
diff --git a/testUserExtension/results-firefox.html b/testUserExtension/results-firefox.html index 1b27b3d..c0115ae 100644 --- a/testUserExtension/results-firefox.html +++ b/testUserExtension/results-firefox.html @@ -54,15 +54,15 @@

Test suite results

totalTime: -29 +43 numTestTotal: -45 +59 numTestPasses: -44 +58 numTestFailures: @@ -70,7 +70,7 @@

Test suite results

numCommandPasses: -67 +198 numCommandFailures: @@ -137,6 +137,20 @@

Test suite results

exitTest - base case exitTest - from within a loop exitTest - from within a function +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 @@ -4750,6 +4764,1243 @@

Test suite results

+ +  + +CreateGlobalVars.html
+ + + + + + + + + +
CreateGlobalVars
getEvalglobalStoredVars = {};
+ + +
+  + +GlobalFunctions.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
functions
functionsetGlobalVar
openhttp://htmlpreview.github.io/
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + +
+  + +GlobalFunctions 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
+ + +
+  + +CallGlobalFunction.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
+ + +
+  + +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
+ +
 
@@ -6144,7 +7395,7 @@ 

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 2.301 sec elapsed: +info: [SelBench] 2.285 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 | | @@ -6302,7 +7553,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.806 sec elapsed: factorial 7 +info: [SelBench] 0.829 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -6425,4 +7676,502 @@

Test suite results

info: Executing: |function | doSubExit | | info: Executing: |exitTest | | | info: [SelBlocks] TEST HALTED +info: Starting test /selenium-server/tests/CreateGlobalVars.html +info: Executing: |getEval | globalStoredVars = {}; | | +info: script is: globalStoredVars = {}; +info: Starting test /selenium-server/tests/GlobalFunctions.html +info: Executing: |function | setGlobalVar | | +info: [SelBlocks] branch => @4: [endFunction] +info: Executing: |endFunction | | | +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 | setGlobalVar | | +info: [SelBlocks] branch => @1: [function|setGlobalVar] +info: Executing: |function | setGlobalVar | | +info: Executing: |open | http://htmlpreview.github.io/ | | +info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | +info: script is: globalStoredVars.aGlobalVar = "set"; +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @8: [call|setGlobalVar] +info: Executing: |call | setGlobalVar | | +info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | +info: script is: globalStoredVars.aGlobalVar; +info: Starting test /selenium-server/tests/GlobalFunctions%202.html +info: Executing: |function | doStuff | | +info: [SelBlocks] branch => @3: [endFunction] +info: Executing: |endFunction | | | +info: Executing: |call | doStuff | | +info: [SelBlocks] branch => @1: [function|doStuff] +info: Executing: |function | doStuff | | +info: Executing: |open | http://htmlpreview.github.io/ | | +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @4: [call|doStuff] +info: Executing: |call | doStuff | | +info: Executing: |assertLocation | http://htmlpreview.github.io/ | | +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 => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: Executing: |function | setGlobalVar | | +info: Executing: |open | http://htmlpreview.github.io/ | | +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: Executing: |call | GlobalFunctions 2.doStuff | | +info: [SelBlocks] branch => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: Executing: |function | doStuff | | +info: Executing: |open | http://htmlpreview.github.io/ | | +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @6: [call|GlobalFunctions 2.doStuff] +info: Executing: |call | GlobalFunctions 2.doStuff | | +info: Executing: |assertLocation | http://htmlpreview.github.io/ | | +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"
\ No newline at end of file diff --git a/testUserExtension/results-googlechrome.html b/testUserExtension/results-googlechrome.html index e5a8825..99a838b 100644 --- a/testUserExtension/results-googlechrome.html +++ b/testUserExtension/results-googlechrome.html @@ -54,15 +54,15 @@

Test suite results

totalTime: -12 +35 numTestTotal: -45 +59 numTestPasses: -44 +58 numTestFailures: @@ -70,7 +70,7 @@

Test suite results

numCommandPasses: -59 +198 numCommandFailures: @@ -137,6 +137,20 @@

Test suite results

exitTest - base case exitTest - from within a loop exitTest - from within a function +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 @@ -2265,7 +2279,7 @@

Test suite results

function subBub - + n @@ -2349,7 +2363,6 @@

Test suite results

"([/~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~/])" - @@ -3201,10 +3214,9 @@

Test suite results

assertEmitted - "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned 2~/])" + "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])" - @@ -3449,7 +3461,7 @@

Test suite results

assertEmitted - "START: 3~iter=3~iter=2~iter=1~END: 0" + "START: 3~iter=3~iter=2~iter=1~END: 3" @@ -4247,7 +4259,7 @@

Test suite 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 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" @@ -4261,20 +4273,15 @@

Test suite results

subtest - - resetEmitted - - - deleteVars sname, srole - - emit - "START ${sname} ${srole}" - + + assertEval + "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}" + true @@ -4282,6 +4289,16 @@

Test suite results

doSomething sname = "dilbert,Q", srole = "goof" + + assertEval + "${_result}" === "sname=dilbert,Q,srole=goof" + true + + + deleteVars + sname, srole + + function @@ -4289,7 +4306,7 @@

Test suite results

sname - emit + return "sname=${sname},srole=${srole}" @@ -4299,16 +4316,41 @@

Test suite results

+ + 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 @@ -4320,21 +4362,25 @@

Test suite results

doSomething 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 @@ -4350,8 +4396,8 @@

Test suite results

- resetEmitted - + deleteVars + sname, srole @@ -4360,7 +4406,7 @@

Test suite results

sname - emit + return "sname=${sname},srole=${srole}" @@ -4374,9 +4420,14 @@

Test suite results

doDeprecated sname = "wally", srole = "lazy" + + assertEval + "${_result}" === "sname=wally,srole=lazy" + true + - assertEmitted - "sname=wally,srole=lazy" + deleteVars + sname, srole @@ -4715,180 +4766,1417 @@

Test suite results

  -
-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 |  |  |
+
+CreateGlobalVars.html
+ + + + + + + + + +
CreateGlobalVars
getEvalglobalStoredVars = {};
+ + +
+  + +GlobalFunctions.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
functions
functionsetGlobalVar
openhttp://htmlpreview.github.io/
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + +
+  + +GlobalFunctions 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
+ + +
+  + +CallGlobalFunction.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
+ + +
+  + +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
+ + +
+  +
+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 |  |  |
@@ -5241,22 +6529,22 @@ 

Test suite results

info: Executing: |emit | "trying" | | info: Executing: |emit | "calling" | | info: Executing: |call | subBub | n = 0 | -info: [SelBlocks] branch => @16: [function|subBub] -info: Executing: |function | subBub | | +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] -info: Executing: |function | subBub | | +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] -info: Executing: |function | subBub | | +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 | | @@ -5291,7 +6579,7 @@

Test suite results

info: Executing: |endTry | bub-invoke | | info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 | info: script is: selblocks.tcf.nestingLevel -info: Executing: |function | subBub | | +info: Executing: |function | subBub | n | info: [SelBlocks] branch => @30: [endFunction] info: Executing: |endFunction | | | info: Executing: |emit | "/])" | | @@ -5578,7 +6866,7 @@

Test suite results

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 2~/])" | | +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 -- @@ -5651,7 +6939,7 @@

Test suite results

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: 0" | | +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 | | @@ -6107,79 +7395,91 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 0.804 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 0" | | +info: [SelBench] 0.682 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: |resetEmitted | | | info: Executing: |deleteVars | sname, srole | | -info: Executing: |emit | "START ${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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @4: [call|doSomething|sname = "dilbert,Q", srole = "goof"] +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 => @7: [endFunction|doSomething] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @8: [call|doSomething|sname = "dogbert", srole = "woof"] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @9: [call|doSomething|sname = "ratbert", srole = "squeak"] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"] +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 => @10: [foreach|sname|"asok", "alice"] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"] +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 => @10: [foreach|sname|"asok", "alice"] +info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"] info: Executing: |foreach | sname | "asok", "alice" | -info: [SelBlocks] branch => @12: [endForeach] +info: [SelBlocks] branch => @20: [endForeach] info: Executing: |endForeach | | | -info: Executing: |emit | "DONE ${sname} ${srole}" | | -info: Executing: |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}" | | +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 @16: [call|NONEXISTENT] Function does not exist: NONEXISTENT. +error: [SelBlocks] Error @23: [call|NONEXISTENT] Function does not exist: NONEXISTENT warn: [SelBlocks] __Stack Trace__ -info: Executing: |resetEmitted | | | +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 => @20: [endScript|doDeprecated] +info: [SelBlocks] branch => @27: [endScript|doDeprecated] info: Executing: |endScript | doDeprecated | | info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" | -info: [SelBlocks] branch => @18: [script|doDeprecated|sname] +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: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endScript | doDeprecated | | -info: [SelBlocks] branch => @21: [call|doDeprecated|sname = "wally", srole = "lazy"] +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: |assertEmitted | "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 | | @@ -6253,7 +7553,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.292 sec elapsed: factorial 7 +info: [SelBench] 0.255 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -6376,4 +7676,502 @@

Test suite results

info: Executing: |function | doSubExit | | info: Executing: |exitTest | | | info: [SelBlocks] TEST HALTED +info: Starting test /selenium-server/tests/CreateGlobalVars.html +info: Executing: |getEval | globalStoredVars = {}; | | +info: script is: globalStoredVars = {}; +info: Starting test /selenium-server/tests/GlobalFunctions.html +info: Executing: |function | setGlobalVar | | +info: [SelBlocks] branch => @4: [endFunction] +info: Executing: |endFunction | | | +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 | setGlobalVar | | +info: [SelBlocks] branch => @1: [function|setGlobalVar] +info: Executing: |function | setGlobalVar | | +info: Executing: |open | http://htmlpreview.github.io/ | | +info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | +info: script is: globalStoredVars.aGlobalVar = "set"; +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @8: [call|setGlobalVar] +info: Executing: |call | setGlobalVar | | +info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | +info: script is: globalStoredVars.aGlobalVar; +info: Starting test /selenium-server/tests/GlobalFunctions%202.html +info: Executing: |function | doStuff | | +info: [SelBlocks] branch => @3: [endFunction] +info: Executing: |endFunction | | | +info: Executing: |call | doStuff | | +info: [SelBlocks] branch => @1: [function|doStuff] +info: Executing: |function | doStuff | | +info: Executing: |open | http://htmlpreview.github.io/ | | +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @4: [call|doStuff] +info: Executing: |call | doStuff | | +info: Executing: |assertLocation | http://htmlpreview.github.io/ | | +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 => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: Executing: |function | setGlobalVar | | +info: Executing: |open | http://htmlpreview.github.io/ | | +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: Executing: |call | GlobalFunctions 2.doStuff | | +info: [SelBlocks] branch => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: Executing: |function | doStuff | | +info: Executing: |open | http://htmlpreview.github.io/ | | +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @6: [call|GlobalFunctions 2.doStuff] +info: Executing: |call | GlobalFunctions 2.doStuff | | +info: Executing: |assertLocation | http://htmlpreview.github.io/ | | +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"
\ No newline at end of file diff --git a/testUserExtension/results-piiexplore.html b/testUserExtension/results-piiexplore.html index 4bf8a1f..e065959 100644 --- a/testUserExtension/results-piiexplore.html +++ b/testUserExtension/results-piiexplore.html @@ -54,31 +54,31 @@

Test suite results

totalTime: -31 +50 numTestTotal: -45 +59 numTestPasses: -44 +54 numTestFailures: -1 +5 numCommandPasses: -59 +196 numCommandFailures: -0 +4 numCommandErrors: -1 +2 Selenium Version: @@ -91,8 +91,8 @@

Test suite results

- - + + @@ -137,6 +137,20 @@

Test suite results

+ + + + + + + + + + + + + +
Test Suite
README
Test Suite
README
eval
branching
if-1
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
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
@@ -147,13 +161,13 @@

Test suite results

README.html
- + - + - +
README
README
open http://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.htmlObject doesn't support this property or method
@@ -2265,7 +2279,7 @@

Test suite results

function subBub - + n @@ -2349,7 +2363,6 @@

Test suite results

"([/~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~/])" - @@ -3201,10 +3214,9 @@

Test suite results

assertEmitted - "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned 2~/])" + "([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])" - @@ -3449,7 +3461,7 @@

Test suite results

assertEmitted - "START: 3~iter=3~iter=2~iter=1~END: 0" + "START: 3~iter=3~iter=2~iter=1~END: 3" @@ -4247,7 +4259,7 @@

Test suite 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 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" @@ -4261,20 +4273,15 @@

Test suite results

subtest - - resetEmitted - - - deleteVars sname, srole - - emit - "START ${sname} ${srole}" - + + assertEval + "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}" + true @@ -4282,6 +4289,16 @@

Test suite results

doSomething sname = "dilbert,Q", srole = "goof" + + assertEval + "${_result}" === "sname=dilbert,Q,srole=goof" + true + + + deleteVars + sname, srole + + function @@ -4289,26 +4306,51 @@

Test suite results

sname - emit + return "sname=${sname},srole=${srole}" - + endFunction doSomething + + 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 @@ -4320,21 +4362,25 @@

Test suite results

doSomething sname = sname, srole = "super=user" + + assertEval + "${_result}" === "sname=${sname},srole=super=user" + true + + + deleteVars + sname, srole + + endForeach - - emit - "DONE ${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}" - + + assertEval + "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}" + true @@ -4350,8 +4396,8 @@

Test suite results

- resetEmitted - + deleteVars + sname, srole @@ -4360,11 +4406,11 @@

Test suite results

sname - emit + return "sname=${sname},srole=${srole}" - + endScript doDeprecated @@ -4374,9 +4420,14 @@

Test suite results

doDeprecated sname = "wally", srole = "lazy" + + assertEval + "${_result}" === "sname=wally,srole=lazy" + true + - assertEmitted - "sname=wally,srole=lazy" + deleteVars + sname, srole @@ -4715,171 +4766,1417 @@

Test suite results

  -
-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__
-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 |  |  |
+
+CreateGlobalVars.html
+ + + + + + + + + +
CreateGlobalVars
getEvalglobalStoredVars = {};
+ + +
+  + +GlobalFunctions.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
functions
functionsetGlobalVar
openhttp://htmlpreview.github.io/Function expected
getEvalglobalStoredVars.aGlobalVar = "set";
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + +
+  + +GlobalFunctions 2.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
+ + +
+  + +CallGlobalFunction.html
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVarCommand 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: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';'
assertEvalglobalStoredVars.aGlobalVar;set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
+ + +
+  + +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
+ + +
+  +
+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: Object doesn't support this property or method
+warn: Stack is: Error: Object doesn't support this property or method
+   at BrowserBot.prototype._isSamePage (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1006:5)
+   at BrowserBot.prototype.pollForLoad (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:945:9)
+   at pollerFunction (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1099:9)
+   at BrowserBot.prototype.runScheduledPollers (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1109:9)
+   at TestLoop.prototype.continueTestWhenConditionIsTrue (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:138:9)
+   at retval (http://htmlpreview.github.io/selenium-server/core/scripts/htmlutils.js:60:5)
+warn: currentTest.recordFailure: Object doesn't support this property or method
+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 |
@@ -5244,22 +6541,22 @@ 

Test suite results

info: Executing: |emit | "trying" | | info: Executing: |emit | "calling" | | info: Executing: |call | subBub | n = 0 | -info: [SelBlocks] branch => @16: [function|subBub] -info: Executing: |function | subBub | | +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] -info: Executing: |function | subBub | | +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] -info: Executing: |function | subBub | | +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 | | @@ -5294,7 +6591,7 @@

Test suite results

info: Executing: |endTry | bub-invoke | | info: Executing: |assertEval | selblocks.tcf.nestingLevel | -1 | info: script is: selblocks.tcf.nestingLevel -info: Executing: |function | subBub | | +info: Executing: |function | subBub | n | info: [SelBlocks] branch => @30: [endFunction] info: Executing: |endFunction | | | info: Executing: |emit | "/])" | | @@ -5581,7 +6878,7 @@

Test suite results

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 2~/])" | | +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 -- @@ -5623,11 +6920,11 @@

Test suite results

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:1848:5) + at Selenium.prototype.doThrow (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2006: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:1082:7) + 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 @@ -5660,7 +6957,7 @@

Test suite results

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: 0" | | +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 | | @@ -6122,80 +7419,92 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 3.211 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 0" | | +info: [SelBench] 3.293 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: |resetEmitted | | | info: Executing: |deleteVars | sname, srole | | -info: Executing: |emit | "START ${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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @4: [call|doSomething|sname = "dilbert,Q", srole = "goof"] +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 => @7: [endFunction|doSomething] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @8: [call|doSomething|sname = "dogbert", srole = "woof"] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @9: [call|doSomething|sname = "ratbert", srole = "squeak"] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"] +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 => @10: [foreach|sname|"asok", "alice"] +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 => @5: [function|doSomething|sname] +info: [SelBlocks] branch => @6: [function|doSomething|sname] info: Executing: |function | doSomething | sname | -info: Executing: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endFunction | doSomething | | -info: [SelBlocks] branch => @11: [call|doSomething|sname = sname, srole = "super=user"] +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 => @10: [foreach|sname|"asok", "alice"] +info: [SelBlocks] branch => @16: [foreach|sname|"asok", "alice"] info: Executing: |foreach | sname | "asok", "alice" | -info: [SelBlocks] branch => @12: [endForeach] +info: [SelBlocks] branch => @20: [endForeach] info: Executing: |endForeach | | | -info: Executing: |emit | "DONE ${sname} ${srole}" | | -info: Executing: |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}" | | +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 @16: [call|NONEXISTENT] Function does not exist: 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: |resetEmitted | | | +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 => @20: [endScript|doDeprecated] +info: [SelBlocks] branch => @27: [endScript|doDeprecated] info: Executing: |endScript | doDeprecated | | info: Executing: |call | doDeprecated | sname = "wally", srole = "lazy" | -info: [SelBlocks] branch => @18: [script|doDeprecated|sname] +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: |emit | "sname=${sname},srole=${srole}" | | -info: Executing: |endScript | doDeprecated | | -info: [SelBlocks] branch => @21: [call|doDeprecated|sname = "wally", srole = "lazy"] +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: |assertEmitted | "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 | | @@ -6269,7 +7578,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 1.181 sec elapsed: factorial 7 +info: [SelBench] 1.247 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -6392,4 +7701,517 @@

Test suite results

info: Executing: |function | doSubExit | | info: Executing: |exitTest | | | info: [SelBlocks] TEST HALTED +info: Starting test /selenium-server/tests/CreateGlobalVars.html +info: Executing: |getEval | globalStoredVars = {}; | | +info: script is: globalStoredVars = {}; +info: Starting test /selenium-server/tests/GlobalFunctions.html +info: Executing: |function | setGlobalVar | | +info: [SelBlocks] branch => @4: [endFunction] +info: Executing: |endFunction | | | +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 | setGlobalVar | | +info: [SelBlocks] branch => @1: [function|setGlobalVar] +info: Executing: |function | setGlobalVar | | +info: Executing: |open | http://htmlpreview.github.io/ | | +error: isNewPageLoaded found an old pageLoadError: Error: Permission denied +warn: currentTest.recordFailure: Function expected +info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | +info: script is: globalStoredVars.aGlobalVar = "set"; +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @8: [call|setGlobalVar] +info: Executing: |call | setGlobalVar | | +info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | +info: script is: globalStoredVars.aGlobalVar; +info: Starting test /selenium-server/tests/GlobalFunctions%202.html +info: Executing: |function | doStuff | | +info: [SelBlocks] branch => @3: [endFunction] +info: Executing: |endFunction | | | +info: Executing: |call | doStuff | | +info: [SelBlocks] branch => @1: [function|doStuff] +info: Executing: |function | doStuff | | +info: Executing: |open | http://htmlpreview.github.io/ | | +warn: currentTest.recordFailure: +info: Executing: |endFunction | | | +info: [SelBlocks] branch => @4: [call|doStuff] +info: Executing: |call | doStuff | | +info: Executing: |assertLocation | http://htmlpreview.github.io/ | | +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 => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: Executing: |function | setGlobalVar | | +info: Executing: |open | http://htmlpreview.github.io/ | | +error: isNewPageLoaded found an old pageLoadError: Error: Object doesn't support this property or method +warn: Stack is: Error: Object doesn't support this property or method + at BrowserBot.prototype._isSamePage (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1006:5) + at BrowserBot.prototype.pollForLoad (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:945:9) + at pollerFunction (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1099:9) + at BrowserBot.prototype.runScheduledPollers (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1109:9) + at TestLoop.prototype.continueTestWhenConditionIsTrue (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:138:9) + at TestLoop.prototype.resume (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:79:13) + at retval (http://htmlpreview.github.io/selenium-server/core/scripts/htmlutils.js:60:5) +warn: currentTest.recordFailure: Object doesn't support this property or method +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 | Object doesn't support this property or method | +error: [SelBlocks] Error While evaluating Javascript expression: function selblocksTemp() { var Object doesn't support this property or method; } +warn: [SelBlocks] __Stack Trace__ +error: Unexpected Exception: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';' +error: Exception details: stack -> SyntaxError: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';' + at assertCompilable (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2918:7) + at Selenium.prototype.doCall (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2594:7) + 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 TestLoop.prototype.resume (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:78:13) + 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: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';' +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"
\ No newline at end of file From d1f4ecc38be315ee2b6d64fe44177d48c8f8b4fc Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 5 Jan 2015 12:58:24 -0500 Subject: [PATCH 102/116] Fixes doCall bug in IE when doCall tries to validate the "argSpec" argument, the validation method was throwing an error in IE if the value was a blank string. We want to be able to call functions without any arguments, so I told it to skip validation when the argSpec is like a blank string. Like a blank string, not exactly a blank string, but like a blank string. parseArgs handles this just fine. --- sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js | 4 +++- user extension/user-extensions.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 5150100..3da84b8 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -1456,7 +1456,9 @@ function $X(xpath, contextNode, resultType) { { 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)"); } if(funcName.match(/[.]/)) { diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index 9c34378..ee19ff0 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -2059,7 +2059,9 @@ function $X(xpath, contextNode, resultType) { { 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)"); } if(funcName.match(/[.]/)) { From 7ee9e0415d313237e61cf303afb9c5be175cd9f9 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 5 Jan 2015 13:24:32 -0500 Subject: [PATCH 103/116] Refactoring tests to test just selblocks there's some kind of bug with selenium in IE, it tries to use the window before it's ready and that is causing our tests to fail if they open pages. I've changed the tests so we're not getting false failures anymore, except for in the readme test, since all it does is open a window. --- sel-blocksTests/CallGlobalFunction.html | 10 ------ sel-blocksTests/CreateGlobalVars.html | 20 ------------ sel-blocksTests/GlobalFunctions 2.html | 41 ------------------------- sel-blocksTests/GlobalFunctions.html | 33 +++----------------- 4 files changed, 4 insertions(+), 100 deletions(-) delete mode 100644 sel-blocksTests/CreateGlobalVars.html delete mode 100644 sel-blocksTests/GlobalFunctions 2.html diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html index d658a24..99202cf 100644 --- a/sel-blocksTests/CallGlobalFunction.html +++ b/sel-blocksTests/CallGlobalFunction.html @@ -35,16 +35,6 @@ globalStoredVars.aGlobalVar; set - - call - GlobalFunctions 2.doStuff - - - - assertLocation - http://htmlpreview.github.io/ - - diff --git a/sel-blocksTests/CreateGlobalVars.html b/sel-blocksTests/CreateGlobalVars.html deleted file mode 100644 index 576a829..0000000 --- a/sel-blocksTests/CreateGlobalVars.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - -CreateGlobalVars - - - - - - - - - - - -
CreateGlobalVars
getEvalglobalStoredVars = {};
- - diff --git a/sel-blocksTests/GlobalFunctions 2.html b/sel-blocksTests/GlobalFunctions 2.html deleted file mode 100644 index 11780c7..0000000 --- a/sel-blocksTests/GlobalFunctions 2.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - -GlobalFunctions 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
- - diff --git a/sel-blocksTests/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html index 8d83941..eeb2c1b 100644 --- a/sel-blocksTests/GlobalFunctions.html +++ b/sel-blocksTests/GlobalFunctions.html @@ -11,13 +11,13 @@ functions - function - setGlobalVar + getEval + globalStoredVars = {}; - open - http://htmlpreview.github.io/ + function + setGlobalVar @@ -30,31 +30,6 @@ - - getEval - globalStoredVars.aGlobalVar = "reset"; - - - - assertNotEval - globalStoredVars.aGlobalVar; - set - - - assertEval - globalStoredVars.aGlobalVar; - reset - - - call - setGlobalVar - - - - assertEval - globalStoredVars.aGlobalVar; - set - From b47f723acb9fddce45db86aac8e6c0a617f8f9c5 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 5 Jan 2015 13:24:54 -0500 Subject: [PATCH 104/116] updates test suite --- sel-blocksTests/_SelBlocks-TestSuite.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index f364afb..9b285e7 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -53,9 +53,7 @@ exitTest - base case exitTest - from within a loop exitTest - from within a function -CreateGlobalVars GlobalFunctions -GlobalFunctions 2 CallGlobalFunction DefineFunctionParameters - Base DefineFunctionParameters - With Default Values From 1716bb5479b0a280452c033dc91a21810cbbf915 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Mon, 5 Jan 2015 13:26:44 -0500 Subject: [PATCH 105/116] Passes testing everywhere. --- IDE test results.html | 142 +++--------- testUserExtension/results-firefox.html | 200 +++------------- testUserExtension/results-googlechrome.html | 194 +++------------- testUserExtension/results-piiexplore.html | 245 ++++---------------- 4 files changed, 148 insertions(+), 633 deletions(-) diff --git a/IDE test results.html b/IDE test results.html index 60708b3..ec8bcdc 100644 --- a/IDE test results.html +++ b/IDE test results.html @@ -18,8 +18,8 @@ - - + +
Test Suite: _SelBlocks-TestSuite.html
Test cases: 59 total / 58 passed / 1 failed
Commands: 999 total / 915 passed / 1 failed / 83 skipped
Test cases: 57 total / 56 passed / 1 failed
Commands: 986 total / 901 passed / 1 failed / 84 skipped

@@ -69,20 +69,18 @@ - - - - - - - - - - - - - - + + + + + + + + + + + +
Index of test cases
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
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
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
@@ -5354,28 +5352,19 @@ -


+


Test case: CreateGlobalVars
- -
Test case: GlobalFunctions
getEval globalStoredVars = {};
- -


+ - - - - - - - + @@ -5387,73 +5376,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Test case: GlobalFunctions
function setGlobalVar
openhttp://htmlpreview.github.io/
getEval globalStoredVars.aGlobalVar = "set";
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
- -


- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Test case: GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
-


+


Test case: CallGlobalFunction
@@ -5483,22 +5409,10 @@ - - - - - - - - - - - -
Test case: CallGlobalFunction
getEval globalStoredVars.aGlobalVar = "reset"; set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
-


+


Test case: DefineFunctionParameters - Base
@@ -5579,7 +5493,7 @@
Test case: DefineFunctionParameters - Base
store original x
-


+


Test case: DefineFunctionParameters - With Default Values
@@ -5873,7 +5787,7 @@
Test case: DefineFunctionParameters - With Default Values
store original x
-


+


Test case: StoreLocal - Function Scope
@@ -5987,7 +5901,7 @@
Test case: StoreLocal - Function Scope
setting a local variable from function scope
-


+


Test case: StoreGlobal - Function Scope
@@ -6083,7 +5997,7 @@
Test case: StoreGlobal - Function Scope
setting a global variable from function scope
-


+


Test case: StoreGlobal - While Scope
@@ -6188,7 +6102,7 @@
Test case: StoreGlobal - While Scope
clearing any values from previous tests
-


+


Test case: StoreLocal - While Scope
@@ -6311,7 +6225,7 @@
Test case: StoreLocal - While Scope
clearing any values from previous tests
-


+


Test case: Store - Behaves as StoreLocal
@@ -6425,7 +6339,7 @@
Test case: Store - Behaves as StoreLocal
setting a local variable from function scope
-


+


Test case: Function - Can Return Value
@@ -6458,7 +6372,7 @@
Test case: Function - Can Return Value
function returnsValue
-


+


Test case: StoreAt - Function Scope Nesting
@@ -6611,7 +6525,7 @@
Test case: StoreAt - Function Scope Nesting
function for setting a variable at it's location / ancestor / parent
-


+


Test case: StoreAt - While Scope Nesting
diff --git a/testUserExtension/results-firefox.html b/testUserExtension/results-firefox.html index c0115ae..1bc931c 100644 --- a/testUserExtension/results-firefox.html +++ b/testUserExtension/results-firefox.html @@ -54,15 +54,15 @@

Test suite results

- + - + - + @@ -70,7 +70,7 @@

Test suite results

- + @@ -137,20 +137,18 @@

Test suite results

- - - - - - - - - - - - - - + + + + + + + + + + + +
Test case: StoreAt - While Scope Nesting
storeAt will set the value of a named variable in a parent scope
totalTime:4333
numTestTotal:5957
numTestPasses:5856
numTestFailures:
numCommandPasses:198193
numCommandFailures:
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
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
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
@@ -4767,115 +4765,38 @@

Test suite results

  -CreateGlobalVars.html
+GlobalFunctions.html
- + -
CreateGlobalVars
functions
getEval globalStoredVars = {};
- - -
-  - -GlobalFunctions.html
- - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
functions
function setGlobalVar
openhttp://htmlpreview.github.io/
getEval globalStoredVars.aGlobalVar = "set";
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
- - -
-  - -GlobalFunctions 2.html
- - - - - - - - - - - - - - - - - - - - - - - -
GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
  -CallGlobalFunction.html
+CallGlobalFunction.html
@@ -4895,7 +4816,7 @@

Test suite results

- + @@ -4905,23 +4826,13 @@

Test suite results

- - - - - - - - - -
CallGlobalFunction
globalStoredVars.aGlobalVar; reset
call GlobalFunctions.setGlobalVar globalStoredVars.aGlobalVar; set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
  -DefineFunctionParameters - Base.html
+DefineFunctionParameters - Base.html
@@ -4997,7 +4908,7 @@

Test suite results

-
DefineFunctionParameters - Base
 
DefineFunctionParameters - With Default Values.html
+
DefineFunctionParameters - With Default Values.html
@@ -5241,7 +5152,7 @@

Test suite results

-
DefineFunctionParameters - With Default Values
 
StoreLocal - Function Scope.html
+
StoreLocal - Function Scope.html
@@ -5337,7 +5248,7 @@

Test suite results

-
StoreLocal - Base
 
StoreGlobal - Function Scope.html
+
StoreGlobal - Function Scope.html
@@ -5421,7 +5332,7 @@

Test suite results

-
StoreGlobal - Function Scope
 
StoreGlobal - While Scope.html
+
StoreGlobal - While Scope.html
@@ -5511,7 +5422,7 @@

Test suite results

-
StoreGlobal - While Scope
 
StoreLocal - While Scope.html
+
StoreLocal - While Scope.html
@@ -5613,7 +5524,7 @@

Test suite results

-
StoreLocal - While Scope
 
Store - Behaves as StoreLocal.html
+
Store - Behaves as StoreLocal.html
@@ -5709,7 +5620,7 @@

Test suite results

-
Store - Behaves as StoreLocal
 
Function - Can Return Value.html
+
Function - Can Return Value.html
@@ -5745,7 +5656,7 @@

Test suite results

-
Function - Can Return Value
 
StoreAt - Function Scope Nesting.html
+
StoreAt - Function Scope Nesting.html
@@ -5869,7 +5780,7 @@

Test suite results

- - - - - - - - - -
StoreAt - Function Scope Nesting
 
StoreAt - While Scope Nesting.html
+
StoreAt - While Scope Nesting.html
@@ -7395,7 +7306,7 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 2.285 sec elapsed: +info: [SelBench] 2.193 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 | | @@ -7553,7 +7464,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.829 sec elapsed: factorial 7 +info: [SelBench] 0.840 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -7676,42 +7587,12 @@

Test suite results

info: Executing: |function | doSubExit | | info: Executing: |exitTest | | | info: [SelBlocks] TEST HALTED -info: Starting test /selenium-server/tests/CreateGlobalVars.html +info: Starting test /selenium-server/tests/GlobalFunctions.html info: Executing: |getEval | globalStoredVars = {}; | | info: script is: globalStoredVars = {}; -info: Starting test /selenium-server/tests/GlobalFunctions.html info: Executing: |function | setGlobalVar | | info: [SelBlocks] branch => @4: [endFunction] info: Executing: |endFunction | | | -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 | setGlobalVar | | -info: [SelBlocks] branch => @1: [function|setGlobalVar] -info: Executing: |function | setGlobalVar | | -info: Executing: |open | http://htmlpreview.github.io/ | | -info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | -info: script is: globalStoredVars.aGlobalVar = "set"; -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @8: [call|setGlobalVar] -info: Executing: |call | setGlobalVar | | -info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | -info: script is: globalStoredVars.aGlobalVar; -info: Starting test /selenium-server/tests/GlobalFunctions%202.html -info: Executing: |function | doStuff | | -info: [SelBlocks] branch => @3: [endFunction] -info: Executing: |endFunction | | | -info: Executing: |call | doStuff | | -info: [SelBlocks] branch => @1: [function|doStuff] -info: Executing: |function | doStuff | | -info: Executing: |open | http://htmlpreview.github.io/ | | -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @4: [call|doStuff] -info: Executing: |call | doStuff | | -info: Executing: |assertLocation | http://htmlpreview.github.io/ | | info: Starting test /selenium-server/tests/CallGlobalFunction.html info: Executing: |getEval | globalStoredVars.aGlobalVar = "reset"; | | info: script is: globalStoredVars.aGlobalVar = "reset"; @@ -7720,9 +7601,8 @@

Test suite results

info: Executing: |assertEval | globalStoredVars.aGlobalVar; | reset | info: script is: globalStoredVars.aGlobalVar; info: Executing: |call | GlobalFunctions.setGlobalVar | | -info: [SelBlocks] branch => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: [SelBlocks] branch => @2: [assertNotEval|globalStoredVars.aGlobalVar;|set] info: Executing: |function | setGlobalVar | | -info: Executing: |open | http://htmlpreview.github.io/ | | info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | info: script is: globalStoredVars.aGlobalVar = "set"; info: Executing: |endFunction | | | @@ -7730,14 +7610,6 @@

Test suite results

info: Executing: |call | GlobalFunctions.setGlobalVar | | info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | info: script is: globalStoredVars.aGlobalVar; -info: Executing: |call | GlobalFunctions 2.doStuff | | -info: [SelBlocks] branch => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] -info: Executing: |function | doStuff | | -info: Executing: |open | http://htmlpreview.github.io/ | | -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @6: [call|GlobalFunctions 2.doStuff] -info: Executing: |call | GlobalFunctions 2.doStuff | | -info: Executing: |assertLocation | http://htmlpreview.github.io/ | | info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20Base.html info: Executing: |store | original | x | info: Executing: |store | original | y | diff --git a/testUserExtension/results-googlechrome.html b/testUserExtension/results-googlechrome.html index 99a838b..4ed48d6 100644 --- a/testUserExtension/results-googlechrome.html +++ b/testUserExtension/results-googlechrome.html @@ -54,15 +54,15 @@

Test suite results

- + - + - + @@ -70,7 +70,7 @@

Test suite results

- + @@ -137,20 +137,18 @@

Test suite results

- - - - - - - - - - - - - - + + + + + + + + + + + +
StoreAt - While Scope Nesting
totalTime:3513
numTestTotal:5957
numTestPasses:5856
numTestFailures:
numCommandPasses:198193
numCommandFailures:
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
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
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
@@ -4767,38 +4765,22 @@

Test suite results

 
CreateGlobalVars.html
+
GlobalFunctions.html
- + -
CreateGlobalVars
functions
getEval globalStoredVars = {};
- - -
 
GlobalFunctions.html
- - - - - - - - - - + @@ -4808,74 +4790,13 @@

Test suite results

- - - - - - - - - - - - - - - - - - - - - - - - - -
functions
function setGlobalVar
openhttp://htmlpreview.github.io/
getEval globalStoredVars.aGlobalVar = "set";
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
- - -
 
GlobalFunctions 2.html
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
 
CallGlobalFunction.html
+
CallGlobalFunction.html
@@ -4905,23 +4826,13 @@

Test suite results

- - - - - - - - - -
CallGlobalFunction
globalStoredVars.aGlobalVar; set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
 
DefineFunctionParameters - Base.html
+
DefineFunctionParameters - Base.html
@@ -4997,7 +4908,7 @@

Test suite results

-
DefineFunctionParameters - Base
 
DefineFunctionParameters - With Default Values.html
+
DefineFunctionParameters - With Default Values.html
@@ -5241,7 +5152,7 @@

Test suite results

-
DefineFunctionParameters - With Default Values
 
StoreLocal - Function Scope.html
+
StoreLocal - Function Scope.html
@@ -5337,7 +5248,7 @@

Test suite results

-
StoreLocal - Base
 
StoreGlobal - Function Scope.html
+
StoreGlobal - Function Scope.html
@@ -5421,7 +5332,7 @@

Test suite results

-
StoreGlobal - Function Scope
 
StoreGlobal - While Scope.html
+
StoreGlobal - While Scope.html
@@ -5511,7 +5422,7 @@

Test suite results

- + +
StoreGlobal - While Scope
 
StoreLocal - While Scope.html
+
StoreLocal - While Scope.html
@@ -5613,7 +5524,7 @@

Test suite results

- - + 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 + + +
StoreLocal - While Scope
 
Store - Behaves as StoreLocal.html
+
Store - Behaves as StoreLocal.html
@@ -5709,7 +5620,7 @@

Test suite results

- - + @@ -33,7 +33,7 @@ - +
Store - Behaves as StoreLocal
 
Function - Can Return Value.html
+
Function - Can Return Value.html
@@ -5745,7 +5656,7 @@

Test suite results

- + + +
Function - Can Return Value
 
StoreAt - Function Scope Nesting.html
+
StoreAt - Function Scope Nesting.html
@@ -5869,7 +5780,7 @@

Test suite results

- - - - - - - - - -
StoreAt - Function Scope Nesting
 
StoreAt - While Scope Nesting.html
+
StoreAt - While Scope Nesting.html
@@ -7553,7 +7464,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.255 sec elapsed: factorial 7 +info: [SelBench] 0.249 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -7676,42 +7587,12 @@

Test suite results

info: Executing: |function | doSubExit | | info: Executing: |exitTest | | | info: [SelBlocks] TEST HALTED -info: Starting test /selenium-server/tests/CreateGlobalVars.html +info: Starting test /selenium-server/tests/GlobalFunctions.html info: Executing: |getEval | globalStoredVars = {}; | | info: script is: globalStoredVars = {}; -info: Starting test /selenium-server/tests/GlobalFunctions.html info: Executing: |function | setGlobalVar | | info: [SelBlocks] branch => @4: [endFunction] info: Executing: |endFunction | | | -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 | setGlobalVar | | -info: [SelBlocks] branch => @1: [function|setGlobalVar] -info: Executing: |function | setGlobalVar | | -info: Executing: |open | http://htmlpreview.github.io/ | | -info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | -info: script is: globalStoredVars.aGlobalVar = "set"; -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @8: [call|setGlobalVar] -info: Executing: |call | setGlobalVar | | -info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | -info: script is: globalStoredVars.aGlobalVar; -info: Starting test /selenium-server/tests/GlobalFunctions%202.html -info: Executing: |function | doStuff | | -info: [SelBlocks] branch => @3: [endFunction] -info: Executing: |endFunction | | | -info: Executing: |call | doStuff | | -info: [SelBlocks] branch => @1: [function|doStuff] -info: Executing: |function | doStuff | | -info: Executing: |open | http://htmlpreview.github.io/ | | -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @4: [call|doStuff] -info: Executing: |call | doStuff | | -info: Executing: |assertLocation | http://htmlpreview.github.io/ | | info: Starting test /selenium-server/tests/CallGlobalFunction.html info: Executing: |getEval | globalStoredVars.aGlobalVar = "reset"; | | info: script is: globalStoredVars.aGlobalVar = "reset"; @@ -7720,9 +7601,8 @@

Test suite results

info: Executing: |assertEval | globalStoredVars.aGlobalVar; | reset | info: script is: globalStoredVars.aGlobalVar; info: Executing: |call | GlobalFunctions.setGlobalVar | | -info: [SelBlocks] branch => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: [SelBlocks] branch => @2: [assertNotEval|globalStoredVars.aGlobalVar;|set] info: Executing: |function | setGlobalVar | | -info: Executing: |open | http://htmlpreview.github.io/ | | info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | info: script is: globalStoredVars.aGlobalVar = "set"; info: Executing: |endFunction | | | @@ -7730,14 +7610,6 @@

Test suite results

info: Executing: |call | GlobalFunctions.setGlobalVar | | info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | info: script is: globalStoredVars.aGlobalVar; -info: Executing: |call | GlobalFunctions 2.doStuff | | -info: [SelBlocks] branch => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] -info: Executing: |function | doStuff | | -info: Executing: |open | http://htmlpreview.github.io/ | | -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @6: [call|GlobalFunctions 2.doStuff] -info: Executing: |call | GlobalFunctions 2.doStuff | | -info: Executing: |assertLocation | http://htmlpreview.github.io/ | | info: Starting test /selenium-server/tests/DefineFunctionParameters%20-%20Base.html info: Executing: |store | original | x | info: Executing: |store | original | y | diff --git a/testUserExtension/results-piiexplore.html b/testUserExtension/results-piiexplore.html index e065959..7a5e8e1 100644 --- a/testUserExtension/results-piiexplore.html +++ b/testUserExtension/results-piiexplore.html @@ -54,31 +54,31 @@

Test suite results

- + - + - + - + - + - + - + @@ -91,7 +91,7 @@

Test suite results

- +
StoreAt - While Scope Nesting
totalTime:5036
numTestTotal:5957
numTestPasses:5455
numTestFailures:52
numCommandPasses:196193
numCommandFailures:41
numCommandErrors:21
Selenium Version:
- + @@ -137,20 +137,18 @@

Test suite results

- - - - - - - - - - - - - - + + + + + + + + + + + +
Test Suite
Test Suite
README
eval
branching
exitTest - base case
exitTest - from within a loop
exitTest - from within a function
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
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
@@ -167,7 +165,7 @@

Test suite results

open http://htmlpreview.github.io/?https://github.com/refactoror/SelBlocks/blob/master/sel-blocksTests/_SelBlocks-testpage.htmlObject doesn't support this property or methodPermission denied
@@ -4767,118 +4765,41 @@

Test suite results

 
CreateGlobalVars.html
+
GlobalFunctions.html
- + -
CreateGlobalVars
functions
getEval globalStoredVars = {};
- - -
 
GlobalFunctions.html
- - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
functions
function setGlobalVar
openhttp://htmlpreview.github.io/Function expected
getEval globalStoredVars.aGlobalVar = "set";
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
- - -
 
GlobalFunctions 2.html
- - - - - - - - - - - - - - - - - - - - - - - - -
GlobalFunctions 2
functiondoStuff
openhttp://htmlpreview.github.io/
endFunction
calldoStuff
assertLocationhttp://htmlpreview.github.io/
 
CallGlobalFunction.html
+
CallGlobalFunction.html
- + @@ -4895,33 +4816,23 @@

Test suite results

- + - + - + - - - - - - - - - -
CallGlobalFunction
CallGlobalFunction
getEval globalStoredVars.aGlobalVar; reset
call GlobalFunctions.setGlobalVarCommand 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: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';'
assertEval globalStoredVars.aGlobalVar; set
callGlobalFunctions 2.doStuff
assertLocationhttp://htmlpreview.github.io/
 
DefineFunctionParameters - Base.html
+
DefineFunctionParameters - Base.html
@@ -4997,7 +4908,7 @@

Test suite results

- - + - + - + @@ -70,7 +70,7 @@

Test suite results

- + @@ -149,6 +149,7 @@

Test suite results

+
DefineFunctionParameters - Base
 
DefineFunctionParameters - With Default Values.html
+
DefineFunctionParameters - With Default Values.html
@@ -5241,7 +5152,7 @@

Test suite results

- + + +
DefineFunctionParameters - With Default Values
 
StoreLocal - Function Scope.html
+
StoreLocal - Function Scope.html
@@ -5337,7 +5248,7 @@

Test suite results

-
StoreLocal - Base
 
StoreGlobal - Function Scope.html
+
StoreGlobal - Function Scope.html
@@ -5421,7 +5332,7 @@

Test suite results

- - + - + - + @@ -70,7 +70,7 @@

Test suite results

- + @@ -149,6 +149,7 @@

Test suite results

+
StoreGlobal - Function Scope
 
StoreGlobal - While Scope.html
+
StoreGlobal - While Scope.html
@@ -5511,7 +5422,7 @@

Test suite results

- + + +
StoreGlobal - While Scope
 
StoreLocal - While Scope.html
+
StoreLocal - While Scope.html
@@ -5613,7 +5524,7 @@

Test suite results

-
StoreLocal - While Scope
 
Store - Behaves as StoreLocal.html
+
Store - Behaves as StoreLocal.html
@@ -5709,7 +5620,7 @@

Test suite results

- - + - + - + @@ -70,7 +70,7 @@

Test suite results

- + @@ -149,6 +149,7 @@

Test suite results

+
Store - Behaves as StoreLocal
 
Function - Can Return Value.html
+
Function - Can Return Value.html
@@ -5745,7 +5656,7 @@

Test suite results

- +
Function - Can Return Value
 
StoreAt - Function Scope Nesting.html
+
StoreAt - Function Scope Nesting.html
@@ -5869,7 +5780,7 @@

Test suite results

-
StoreAt - Function Scope Nesting
 
StoreAt - While Scope Nesting.html
+
StoreAt - While Scope Nesting.html
@@ -6006,15 +5917,15 @@

Test suite results

StoreAt - While Scope Nesting
 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: Object doesn't support this property or method
-warn: Stack is: Error: Object doesn't support this property or method
-   at BrowserBot.prototype._isSamePage (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1006:5)
+error: isNewPageLoaded found an old pageLoadError: Error: Permission denied
+warn: Stack is: Error: Permission denied
+   at BrowserBot.prototype._isSamePage (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:987:5)
    at BrowserBot.prototype.pollForLoad (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:945:9)
    at pollerFunction (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1099:9)
    at BrowserBot.prototype.runScheduledPollers (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1109:9)
    at TestLoop.prototype.continueTestWhenConditionIsTrue (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:138:9)
    at retval (http://htmlpreview.github.io/selenium-server/core/scripts/htmlutils.js:60:5)
-warn: currentTest.recordFailure: Object doesn't support this property or method
+warn: currentTest.recordFailure: Permission denied
 info: Starting test /selenium-server/tests/eval.html
 info: Executing: |resetEmitted |  |  |
 info: Executing: |emit | "dilbert".isOneOf("dilbert","dogbert","mordac") |  |
@@ -7419,7 +7330,7 @@ 

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 3.293 sec elapsed: +info: [SelBench] 3.468 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 | | @@ -7578,7 +7489,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 1.247 sec elapsed: factorial 7 +info: [SelBench] 1.236 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -7701,45 +7612,12 @@

Test suite results

info: Executing: |function | doSubExit | | info: Executing: |exitTest | | | info: [SelBlocks] TEST HALTED -info: Starting test /selenium-server/tests/CreateGlobalVars.html +info: Starting test /selenium-server/tests/GlobalFunctions.html info: Executing: |getEval | globalStoredVars = {}; | | info: script is: globalStoredVars = {}; -info: Starting test /selenium-server/tests/GlobalFunctions.html info: Executing: |function | setGlobalVar | | info: [SelBlocks] branch => @4: [endFunction] info: Executing: |endFunction | | | -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 | setGlobalVar | | -info: [SelBlocks] branch => @1: [function|setGlobalVar] -info: Executing: |function | setGlobalVar | | -info: Executing: |open | http://htmlpreview.github.io/ | | -error: isNewPageLoaded found an old pageLoadError: Error: Permission denied -warn: currentTest.recordFailure: Function expected -info: Executing: |getEval | globalStoredVars.aGlobalVar = "set"; | | -info: script is: globalStoredVars.aGlobalVar = "set"; -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @8: [call|setGlobalVar] -info: Executing: |call | setGlobalVar | | -info: Executing: |assertEval | globalStoredVars.aGlobalVar; | set | -info: script is: globalStoredVars.aGlobalVar; -info: Starting test /selenium-server/tests/GlobalFunctions%202.html -info: Executing: |function | doStuff | | -info: [SelBlocks] branch => @3: [endFunction] -info: Executing: |endFunction | | | -info: Executing: |call | doStuff | | -info: [SelBlocks] branch => @1: [function|doStuff] -info: Executing: |function | doStuff | | -info: Executing: |open | http://htmlpreview.github.io/ | | -warn: currentTest.recordFailure: -info: Executing: |endFunction | | | -info: [SelBlocks] branch => @4: [call|doStuff] -info: Executing: |call | doStuff | | -info: Executing: |assertLocation | http://htmlpreview.github.io/ | | info: Starting test /selenium-server/tests/CallGlobalFunction.html info: Executing: |getEval | globalStoredVars.aGlobalVar = "reset"; | | info: script is: globalStoredVars.aGlobalVar = "reset"; @@ -7748,36 +7626,15 @@

Test suite results

info: Executing: |assertEval | globalStoredVars.aGlobalVar; | reset | info: script is: globalStoredVars.aGlobalVar; info: Executing: |call | GlobalFunctions.setGlobalVar | | -info: [SelBlocks] branch => @1: [getEval|globalStoredVars.aGlobalVar = "reset";] +info: [SelBlocks] branch => @2: [assertNotEval|globalStoredVars.aGlobalVar;|set] info: Executing: |function | setGlobalVar | | -info: Executing: |open | http://htmlpreview.github.io/ | | -error: isNewPageLoaded found an old pageLoadError: Error: Object doesn't support this property or method -warn: Stack is: Error: Object doesn't support this property or method - at BrowserBot.prototype._isSamePage (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1006:5) - at BrowserBot.prototype.pollForLoad (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:945:9) - at pollerFunction (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1099:9) - at BrowserBot.prototype.runScheduledPollers (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1109:9) - at TestLoop.prototype.continueTestWhenConditionIsTrue (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:138:9) - at TestLoop.prototype.resume (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:79:13) - at retval (http://htmlpreview.github.io/selenium-server/core/scripts/htmlutils.js:60:5) -warn: currentTest.recordFailure: Object doesn't support this property or method 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 | Object doesn't support this property or method | -error: [SelBlocks] Error While evaluating Javascript expression: function selblocksTemp() { var Object doesn't support this property or method; } -warn: [SelBlocks] __Stack Trace__ -error: Unexpected Exception: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';' -error: Exception details: stack -> SyntaxError: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';' - at assertCompilable (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2918:7) - at Selenium.prototype.doCall (http://htmlpreview.github.io/selenium-server/core/scripts/user-extensions.js:2594:7) - 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 TestLoop.prototype.resume (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:78:13) - 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: @4: [call|GlobalFunctions.setGlobalVar] Invalid call parameter(s) 'Object doesn't support this property or method': Expected ';' +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 | From b408f6d27217d97dfe5ceab4ff0fb4240324da08 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 6 Jan 2015 19:14:03 -0500 Subject: [PATCH 106/116] Updates docs on testing the user-extensions.js --- testUserExtension/README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/testUserExtension/README.md b/testUserExtension/README.md index ebd498b..a673a1c 100644 --- a/testUserExtension/README.md +++ b/testUserExtension/README.md @@ -44,6 +44,8 @@ Then run `createSelbenchUserExtensions.cmd` 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 @@ -68,4 +70,24 @@ To run the automatic tests in firefox googlechrome and internet explorer do 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 \ No newline at end of file +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 From b58b0d4240e3da4892a58bb215cb12803eea4ae6 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 6 Jan 2015 20:33:07 -0500 Subject: [PATCH 107/116] Updates root readme. --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c6549fe..dc7b5a1 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,58 @@ SelBlocks 2 ========= -SelBlocks is a language extension for Selenese that works on both the Selenium IDE and Selenium standalone server. +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 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* + * storeLocal : stores variables in the current block scope + * 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 available from the firefox addons site, or just search for it in your addons menu. + +The Selenium server extension file is in "/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 -[Firefox Installer](https://addons.mozilla.org/en-US/firefox/addon/selenium-ide-sel-blocks/) / [Documentation](http://refactoror.wikia.com/wiki/Selblocks_Reference) +* [Chris Noe](https://github.com/refactoror) -The Selenium server user-extensions.js file is in "/user extension/user-extensions.js". Grab a copy and follow the directions in the SeleniumHTMLRunner.cmd file. +# 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. From 47e8f2d7cabd2550c40052dc08d61e70c0cb3902 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 6 Jan 2015 20:39:29 -0500 Subject: [PATCH 108/116] root readme, aesthetics --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index dc7b5a1..697e2d9 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ -SelBlocks 2 -========= +# SelBlocks 2 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 so easy a child could do it. Seriously, we've taught kids how to use this. -> 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. +> 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`. @@ -36,21 +35,21 @@ SelBlocks is a language extension for Selenese that works on both the Selenium I * *Scoped storeAttribute* : stores the value of the located attribute. * SelBlocks adds : storeLocalAttribute, storeGlobalAttribute, and storeAtAttribute -# Installation +## Installation The [Firefox installer](https://addons.mozilla.org/en-US/firefox/addon/selenium-ide-sel-blocks/) is available from the firefox addons site, or just search for it in your addons menu. The Selenium server extension file is in "/user extension/user-extensions.js". Grab a copy and follow the directions in the SeleniumHTMLRunner.cmd file. -# Documentation +## Documentation Find the docs at http://refactoror.wikia.com/wiki/Selblocks_Reference -# Author +## Author * [Chris Noe](https://github.com/refactoror) -# Contributors +## Contributors * [Matthew Kastor](https://github.com/matthewkastor) From f58ff76572703b50cfb514643f291b2df0f32e91 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 6 Jan 2015 20:49:00 -0500 Subject: [PATCH 109/116] root readme, typos, notes --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 697e2d9..9a1651c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # SelBlocks 2 -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 so easy a child could do it. Seriously, we've taught kids how to use this. +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. > 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 @@ -22,8 +22,8 @@ SelBlocks is a language extension for Selenese that works on both the Selenium I * forJson, forXml * exitTest * Adds the following variable declarators to Selenese: - * *Scoped Store* - * storeLocal : stores variables in the current block scope + * *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. From a47832e58b1b681cbd41630f1168472ccc65205f Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 6 Jan 2015 21:20:16 -0500 Subject: [PATCH 110/116] adds notes about installing dev, or published --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a1651c..00cd263 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,11 @@ SelBlocks is a language extension for Selenese that works on both the Selenium I ## Installation -The [Firefox installer](https://addons.mozilla.org/en-US/firefox/addon/selenium-ide-sel-blocks/) is available from the firefox addons site, or just search for it in your addons menu. +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. -The Selenium server extension file is in "/user extension/user-extensions.js". Grab a copy and follow the directions in the SeleniumHTMLRunner.cmd file. +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 From 6e6bc8cda07a1e3ba9e0ee95eeecc07d7df8b493 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 6 Jan 2015 21:34:58 -0500 Subject: [PATCH 111/116] adds selblocks logo to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 00cd263..67e115a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # SelBlocks 2 +![SelBlocks Logo](https://raw.githubusercontent.com/refactorer/SelBlocks/master/sel-blocks-fx_xpi/chrome/skin/selblocksLogo.png) 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. From 585358fb116894813ab690dbef915bea7ab152cd Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Tue, 6 Jan 2015 21:36:29 -0500 Subject: [PATCH 112/116] fixes typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 67e115a..fe08373 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # SelBlocks 2 -![SelBlocks Logo](https://raw.githubusercontent.com/refactorer/SelBlocks/master/sel-blocks-fx_xpi/chrome/skin/selblocksLogo.png) +![SelBlocks Logo](https://raw.githubusercontent.com/refactoror/SelBlocks/master/sel-blocks-fx_xpi/chrome/skin/selblocksLogo.png) 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. From 539f0a4998a6399ca153c9ffe448ae80fced0dfa Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Wed, 7 Jan 2015 22:03:04 -0500 Subject: [PATCH 113/116] adds test for special keys vars The "KEY_" variables were being wiped out. Now they're not. --- IDE test results.html | 26 +++++++++++++-- sel-blocksTests/_SelBlocks-TestSuite.html | 1 + .../sendkeys keys are preserved.html | 32 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 sel-blocksTests/sendkeys keys are preserved.html diff --git a/IDE test results.html b/IDE test results.html index ec8bcdc..d24f494 100644 --- a/IDE test results.html +++ b/IDE test results.html @@ -18,8 +18,8 @@ - - + +
Test Suite: _SelBlocks-TestSuite.html
Test cases: 57 total / 56 passed / 1 failed
Commands: 986 total / 901 passed / 1 failed / 84 skipped
Test cases: 58 total / 57 passed / 1 failed
Commands: 989 total / 904 passed / 1 failed / 84 skipped

@@ -81,6 +81,7 @@ +
Index of test cases
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
@@ -6690,4 +6691,25 @@
+


+ + + + + + + + + + + + + + + + + + +
Test case: sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 9b285e7..eeae016 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -65,6 +65,7 @@
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
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
+ + From 8a36d9bfb5df10e883496ec8abce1389febce0ce Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Wed, 7 Jan 2015 22:03:37 -0500 Subject: [PATCH 114/116] fixes bug clearing special keys --- .../chrome/content/extensions/selblocks.js | 13 +++++-------- user extension/user-extensions.js | 13 +++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index 3da84b8..d57ec40 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -206,14 +206,11 @@ function $X(xpath, contextNode, resultType) { * @methodOf ContextManager. */ ContextManager.prototype.reset = function exitContext() { - if (this.contexts.length > 0) { - storedVars = storedVarsGlobal; - storedVarsLocal = storedVarsGlobal; - this.contexts = []; - this.enter(); - } else { - throw new Error("No context to exit from"); - } + storedVars = storedVarsGlobal; + build_sendkeys_maps(); + storedVarsLocal = storedVarsGlobal; + this.contexts = []; + this.enter(); }; /** * Stores variable into the context chain in the last parent where it was diff --git a/user extension/user-extensions.js b/user extension/user-extensions.js index ee19ff0..dce49b7 100644 --- a/user extension/user-extensions.js +++ b/user extension/user-extensions.js @@ -809,14 +809,11 @@ function $X(xpath, contextNode, resultType) { * @methodOf ContextManager. */ ContextManager.prototype.reset = function exitContext() { - if (this.contexts.length > 0) { - storedVars = storedVarsGlobal; - storedVarsLocal = storedVarsGlobal; - this.contexts = []; - this.enter(); - } else { - throw new Error("No context to exit from"); - } + storedVars = storedVarsGlobal; + build_sendkeys_maps(); + storedVarsLocal = storedVarsGlobal; + this.contexts = []; + this.enter(); }; /** * Stores variable into the context chain in the last parent where it was From 5ad5a3f8fb75d1af9f3fe1e9a2b21a9eea13da95 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Wed, 7 Jan 2015 22:04:04 -0500 Subject: [PATCH 115/116] server test results --- testUserExtension/results-firefox.html | 47 ++++++++++++++--- testUserExtension/results-googlechrome.html | 47 ++++++++++++++--- testUserExtension/results-piiexplore.html | 56 +++++++++++++++------ 3 files changed, 124 insertions(+), 26 deletions(-) diff --git a/testUserExtension/results-firefox.html b/testUserExtension/results-firefox.html index 1bc931c..46bf439 100644 --- a/testUserExtension/results-firefox.html +++ b/testUserExtension/results-firefox.html @@ -54,15 +54,15 @@

Test suite results

totalTime:3335
numTestTotal:5758
numTestPasses:5657
numTestFailures:
numCommandPasses:193196
numCommandFailures:
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
@@ -5912,6 +5913,33 @@

Test suite results

+
 
sendkeys keys are preserved.html
+ + + + + + + + + + + + + + + + + + + + +
sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ +
 
@@ -7306,7 +7334,7 @@ 

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 2.193 sec elapsed: +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 | | @@ -7464,7 +7492,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.840 sec elapsed: factorial 7 +info: [SelBench] 0.826 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -8046,4 +8074,11 @@

Test suite results

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 index 4ed48d6..e1f227b 100644 --- a/testUserExtension/results-googlechrome.html +++ b/testUserExtension/results-googlechrome.html @@ -54,15 +54,15 @@

Test suite results

totalTime:1315
numTestTotal:5758
numTestPasses:5657
numTestFailures:
numCommandPasses:193196
numCommandFailures:
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
@@ -5912,6 +5913,33 @@

Test suite results

+
 
sendkeys keys are preserved.html
+ + + + + + + + + + + + + + + + + + + + +
sendkeys keys are preserved
assertEval"KEY_ENTER" in storedVarstrue
assertEval"KEY_TAB" in storedVarstrue
assertEval"KEY_BACKSPACE" in storedVarstrue
+ +
 
@@ -7306,7 +7334,7 @@ 

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 0.682 sec elapsed: +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 | | @@ -7464,7 +7492,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 0.249 sec elapsed: factorial 7 +info: [SelBench] 0.309 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -8046,4 +8074,11 @@

Test suite results

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 index 7a5e8e1..3e9993f 100644 --- a/testUserExtension/results-piiexplore.html +++ b/testUserExtension/results-piiexplore.html @@ -54,15 +54,15 @@

Test suite results

totalTime:3638
numTestTotal:5758
numTestPasses:5556
numTestFailures:
numCommandPasses:193196
numCommandFailures:
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
@@ -5912,19 +5913,39 @@

Test suite results

+
 
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: Stack is: Error: Permission denied
-   at BrowserBot.prototype._isSamePage (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:987:5)
-   at BrowserBot.prototype.pollForLoad (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:945:9)
-   at pollerFunction (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1099:9)
-   at BrowserBot.prototype.runScheduledPollers (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-browserbot.js:1109:9)
-   at TestLoop.prototype.continueTestWhenConditionIsTrue (http://htmlpreview.github.io/selenium-server/core/scripts/selenium-executionloop.js:138:9)
-   at retval (http://htmlpreview.github.io/selenium-server/core/scripts/htmlutils.js:60:5)
 warn: currentTest.recordFailure: Permission denied
 info: Starting test /selenium-server/tests/eval.html
 info: Executing: |resetEmitted |  |  |
@@ -6831,7 +6852,7 @@ 

Test suite results

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:2006:5) + 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) @@ -7330,7 +7351,7 @@

Test suite results

info: Executing: |endWhile | | | info: Executing: |emit | "END ${i}" | | info: Executing: |timerElapsed | | | -info: [SelBench] 3.468 sec elapsed: +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 | | @@ -7489,7 +7510,7 @@

Test suite results

info: [SelBlocks] branch => @5: [call|fac|n=degree] info: Executing: |call | fac | n=degree | info: Executing: |timerElapsed | | | -info: [SelBench] 1.236 sec elapsed: factorial 7 +info: [SelBench] 1.226 sec elapsed: factorial 7 info: Executing: |emit | degree + "!=" + _result | | info: Executing: |function | fac | n | info: [SelBlocks] branch => @16: [endFunction] @@ -8071,4 +8092,11 @@

Test suite results

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 From 0e889f699b9235a09deb543326abe1b015af37b4 Mon Sep 17 00:00:00 2001 From: Matthew Kastor Date: Sun, 18 Jan 2015 20:00:44 -0500 Subject: [PATCH 116/116] nested global funcs bug --- sel-blocksTests/CallGlobalFunction.html | 4 +- .../CallGlobalFunctionNesting.html | 47 +++++++++++++++++++ sel-blocksTests/GlobalFunctions.html | 2 +- sel-blocksTests/GlobalFunctions2.html | 37 +++++++++++++++ sel-blocksTests/_SelBlocks-TestSuite.html | 2 + 5 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 sel-blocksTests/CallGlobalFunctionNesting.html create mode 100644 sel-blocksTests/GlobalFunctions2.html diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html index 99202cf..3eb13b0 100644 --- a/sel-blocksTests/CallGlobalFunction.html +++ b/sel-blocksTests/CallGlobalFunction.html @@ -18,7 +18,7 @@
assertNotEval globalStoredVars.aGlobalVar;setnot set
assertEval
assertEval globalStoredVars.aGlobalVar;setnot 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/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html index eeb2c1b..81e6a49 100644 --- a/sel-blocksTests/GlobalFunctions.html +++ b/sel-blocksTests/GlobalFunctions.html @@ -22,7 +22,7 @@
getEvalglobalStoredVars.aGlobalVar = "set";globalStoredVars.aGlobalVar = "not set";
+ + + + + + + + + + + + + + + + + + + + + + + + +
GlobalFunctions2
functionsetGlobalVar2
getEvalglobalStoredVars.aGlobalVar = "is set";
callGlobalFunctions.setGlobalVar
endFunction
+ + diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index eeae016..990e79a 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -66,6 +66,8 @@
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
sendkeys keys are preserved
GlobalFunctions2
CallGlobalFunctionNesting