Module: AssertJavaScript
- Includes:
- AssertXPath
- Defined in:
- lib/assert_javascript.rb
Overview
See: assertxpath.rubyforge.org/ %html <pre>
#\ #.:# +------------------------------------------+
#\ #.:# ^^^^^ ___/ these assertions use Javascript::PurePerl \
#\ #.:# }OvO{ <___ to convert JS into XML. assert_xpath can |
##.:# {| |} | query this to find important details, |
#..# \| |/ \ and safely skip over unimportant details! /
#..# \ _ / +------------------------------------------+
#..# | |
#..#>=======d=b=======
#..#
%html </pre>
Constant Summary
Constants included from AssertXPath
Instance Method Summary collapse
-
#assert_javascript(source = nil, diagnostic = nil) ⇒ Object
(also: #assert_js)
%html <a name=‘assert_javascript’></a> Wraps
Javascript::PurePerl
to convert JavaScript into XML describing each lexeme. -
#assert_javascript_too(&block) ⇒ Object
:nodoc: # ERGO merge with assert_javascript!!!.
-
#assert_js_argument(index = 1, diagnostic = nil) ⇒ Object
Explores a function call’s argument list *
index
- 1-based index into the arguments *diagnostic
- optional string to add to failure message. -
#assert_js_call(*args, &block) ⇒ Object
Not ready for public use!.
-
#assert_js_hide(element_id) ⇒ Object
Alias for assert_js_show(element_id, :hide).
-
#assert_js_if(*args, &block) ⇒ Object
Find a JavaScript if statement, or one of its elements * *args - ERGO! *
diagnostic
- optional string to add to failure message. -
#assert_js_insert_html(orientation, element_id, matcher = //, diagnostic = nil) ⇒ Object
Detects an Insertion attack.
-
#assert_js_remote_function(action = nil, tag_id = nil, diagnostic = nil) ⇒ Object
Detects an
Ajax.Update
orAjax.Request
call *action
- optional - the HTTP Post action - the first argument toAjax.Update
orAjax.Request
*tag_id
- any of the following * -:request
- * -:update
- *diagnostic
- optional string to add to failure message. -
#assert_js_replace_html(element_id, matcher = nil, diagnostic = nil, &block) ⇒ Object
Detect the JavaScriptGenerator method
replace_html
*element_id
- first argument toreplace_html
- the target HTML Element’sid
*matcher
- optional regular expression to match the raw contents of the second argument toreplace_html
*diagnostic
- optional string to add to failure message *block
- optional; permitsassert_xpath
calls into the HTML contents of the replacement. -
#assert_js_show(element_id, visibility = :show) ⇒ Object
%html <a name=‘assert_js_show’></a> Detects the Element.show or Element.hide commands *
element_id
- HTML Elementid
to target *visibility
- defaults to :show; optionally :hide. -
#assert_js_xml(q) ⇒ Object
Not ready for public use!.
-
#assert_json(jsonic = @xdoc || assert_javascript, diagnostic = nil) ⇒ Object
%html <a name=‘assert_json’></a> Converts a REXML::Element into a Hash containing named elements.
-
#assert_uri(uri) ⇒ Object
Not ready for public use yet!.
-
#deny_javascript(source = nil, diagnostic = nil) ⇒ Object
(also: #deny_js)
Negates
assert_javascript
. - #deny_js_argument(index = 1, diagnostic = nil) ⇒ Object
-
#deny_js_call(*args) ⇒ Object
-
++ - *
diagnostic
- optional string to add to failure message.
-
-
#deny_js_if(condition = :all, matcher = nil, diagnostic = nil) ⇒ Object
Fails if a JavaScript
if
expression or block has the given characteristics * *args - ERGO! *diagnostic
- optional string to add to failure message. -
#deny_js_replace_html(element_id, matcher = nil, diagnostic = nil) ⇒ Object
Negates assert_js_replace_html *
element_id
- first argument toreplace_html
- the target HTML Element’sid
*matcher
- optional regular expression to not match the raw contents of the second argument toreplace_html
*diagnostic
- optional string to add to failure message If thematcher
isnil
or not provided, theelement_id
must /not/ match anyElement.update
call in its context. -
#returning(value) {|value| ... } ⇒ Object
:nodoc:.
Methods included from AssertXPath
#assert_any_xpath, #assert_hpricot, #assert_libxml, #assert_rexml, #assert_tag_id, #assert_tidy, #assert_xml, #assert_xpath, #deny_any_xpath, #deny_tag_id, #deny_xpath, #drill, #indent_xml, #invoke_hpricot, #invoke_libxml, #invoke_rexml, #using, #validate_as
Instance Method Details
#assert_javascript(source = nil, diagnostic = nil) ⇒ Object Also known as: assert_js
%html <a name=‘assert_javascript’></a> Wraps Javascript::PurePerl
to convert JavaScript into XML describing each lexeme. This allows subsequent assert_xpath
calls to read the JavaScript.
See Javascript::PurePerl for Ruby Enthusiasts to learn to install Javascript::PurePerl
-
source
- optional string containing JavaScript. The default is@response.body
-
diagnostic
- optional string to add to failure message
Other assert_js_
* methods call assert_javascript
if the secret @xdoc
instance variable is nil
To extract JS from an XHTML page, place the assert_js
inside the assert_xpath
which located your JavaScript. For example:
assert_xpath './/input[ @type = "image" ]' do |input|
assert_javascript input.onclick
assert_xpath './/Statement[2]' do
assert_js_remote_function '/user/inventory/' do
json = assert_js_argument(2)
path, query = assert_uri('path?' + json[:parameters])
assert_equal @user.id.to_s, query[:user_id]
assert_equal @user.inventory.first.id.to_s, query[:inventory_id]
end
end
end
assert_tag_id :div, :inventory_bar # <-- applies to original XML
See: AssertJavaScriptTest#test_assert_javascript
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/assert_javascript.rb', line 76 def assert_javascript(source = nil, diagnostic = nil) javascript_to_xml(source, diagnostic) do |tmp_error| @xdoc = assert_xpath( '/AST/Program/SourceElements', ( diagnostic, "JavaScript <#{source}> contained errors:\n#{File.read(tmp_error) rescue nil}" ) ) end # ERGO if any diagnostic is a lambda, lazily evaluate it end |
#assert_javascript_too(&block) ⇒ Object
:nodoc: # ERGO merge with assert_javascript!!!
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/assert_javascript.rb', line 89 def assert_javascript_too(&block) #:nodoc: # ERGO merge with assert_javascript!!! @xdoc or assert_javascript sit_and_spin = './/VariableDeclaration/' + 'Identifier[ @name = "Identifier" ]/../' + 'Initializer[ @name = "Initializer" ]/' + 'Number[ @name = "AssignmentExpression" ]/../..' stuff = {} @xdoc.each_element(sit_and_spin) do |node| name = node.get_path('.//Identifier').text number = node.get_path('.//Number').text stuff[name.to_sym] = number.to_f # ERGO is to_f best? # ERGO simpler way to add an ostruct member? # ERGO cleaner XPath... end js = OpenStruct.new(stuff) block.call(js) end |
#assert_js_argument(index = 1, diagnostic = nil) ⇒ Object
Explores a function call’s argument list
-
index
- 1-based index into the arguments -
diagnostic
- optional string to add to failure message
Example: AssertJavaScriptTest#test_assert_js_argument
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/assert_javascript.rb', line 220 def assert_js_argument(index = 1, diagnostic = nil) @xdoc or assert_javascript # ERGO rdoc: what do we depend on? # ERGO propagate xpathic 'descendant-or-self' assert_xpath xpath_argument(index), diagnostic do |node| return node.text if %w(String Identifier).include?(node.name) return assert_json if node.name == 'ObjectLiteral' end # ERGO test we slip not into a nested argument list end |
#assert_js_call(*args, &block) ⇒ Object
Not ready for public use!
Example:
409 410 411 412 |
# File 'lib/assert_javascript.rb', line 409 def assert_js_call(*args, &block) path, arg1, arg2, diagnostic = *calling_js_path(args) assert_xpath path, diagnostic, &block end |
#assert_js_hide(element_id) ⇒ Object
Alias for assert_js_show(element_id, :hide)
440 |
# File 'lib/assert_javascript.rb', line 440 def assert_js_hide(element_id) assert_js_show(element_id, :hide) end |
#assert_js_if(*args, &block) ⇒ Object
Find a JavaScript if statement, or one of its elements
-
*args - ERGO!
-
diagnostic
- optional string to add to failure message
Example:
448 449 450 |
# File 'lib/assert_javascript.rb', line 448 def assert_js_if(*args, &block) return assert_any_xpath(*_re_arg_if(*args), &block) end |
#assert_js_insert_html(orientation, element_id, matcher = //, diagnostic = nil) ⇒ Object
Detects an Insertion attack.
-
orientation
-:top
,:bottom
, etc…
Remaining arguments similar to assert_js_replace_html
Example: %transclude AssertJavaScriptTest#test_assert_js_insert_html
321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/assert_javascript.rb', line 321 def assert_js_insert_html(orientation, element_id, matcher = //, diagnostic = nil) orientation = orientation.to_s.capitalize # ERGO the matcher should work the same as assert_js_replace_html assert_any_xpath object_method_xpath('Insertion', orientation, element_id), matcher, diagnostic do assert_equal element_id.to_s, assert_js_argument(1), diagnostic # note: shouldn't happen! assert_js_xml(assert_js_argument(2)) # ERGO good error diagnostic if _this_ fails! yield if block_given? # ERGO yield something? return @xdoc # ERGO everyone should return their guts like this end end |
#assert_js_remote_function(action = nil, tag_id = nil, diagnostic = nil) ⇒ Object
Detects an Ajax.Update
or Ajax.Request
call
-
action
- optional - the HTTP Post action - the first argument toAjax.Update
orAjax.Request
-
tag_id
- any of the following -
:request
-
-
-
:update
-
-
-
diagnostic
- optional string to add to failure message
Example:
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/assert_javascript.rb', line 344 def assert_js_remote_function( action = nil, tag_id = nil, diagnostic = nil ) matcher = // # ERGO method = if tag_id.class === String or tag_id.class == Regexp # ERGO test regexp 'Update' elsif tag_id == :request # ERGO test this branch 'Request' elsif tag_id == :update # ERGO test this branch 'Update' else "Request' or . = 'Update" end xpath = object_method_xpath('Ajax', method, action) # ERGO search via tag_id!!! assert_any_xpath xpath, //, diagnostic do if (tag_id.class != String and tag_id.class != Regexp) or /#{tag_id}/ =~ assert_js_argument(2) if action # ERGO move those GCI::unescapeHTMLs up the food chain? assert_equal CGI::unescapeHTML(action), CGI::unescapeHTML(assert_js_argument(1)), diagnostic end # ERGO a better system to extract GET parameters yield if block_given? # ERGO test this block return @xdoc # ERGO test that return end end # ERGO less confusing error diagnostic if this fails flunk (diagnostic, "expected id <#{tag_id}>") end |
#assert_js_replace_html(element_id, matcher = nil, diagnostic = nil, &block) ⇒ Object
Detect the JavaScriptGenerator method replace_html
-
element_id
- first argument toreplace_html
- the target HTML Element’sid
-
matcher
- optional regular expression to match the raw contents of the second argument toreplace_html
-
diagnostic
- optional string to add to failure message -
block
- optional; permitsassert_xpath
calls
into the HTML contents of the replacement
Example: AssertJavaScriptTest#test_assert_js_replace_html
269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/assert_javascript.rb', line 269 def assert_js_replace_html(element_id, matcher = nil, diagnostic = nil, &block) assert_xpath object_method_xpath('Element', 'update', element_id), diagnostic do assert_equal element_id.to_s, assert_js_argument(1) assert_match matcher, assert_js_argument(2), diagnostic if matcher # ERGO fetch argument 2 as yielded xml and match its inner text if block assert_js_xml(assert_js_argument(2)) # ERGO do this even without the if block.call end end end |
#assert_js_show(element_id, visibility = :show) ⇒ Object
%html <a name=‘assert_js_show’></a> Detects the Element.show or Element.hide commands
-
element_id
- HTML Elementid
to target -
visibility
- defaults to :show; optionally :hide
431 432 433 434 435 436 |
# File 'lib/assert_javascript.rb', line 431 def assert_js_show(element_id, visibility = :show) # ERGO also deny, also diagnostic assert_xpath object_method_xpath(:Element, visibility, element_id) do assert_equal element_id.to_s, assert_js_argument(1) end # ERGO what if the visibility is wrong? end |
#assert_js_xml(q) ⇒ Object
Not ready for public use!
395 396 397 398 399 400 401 402 403 |
# File 'lib/assert_javascript.rb', line 395 def assert_js_xml(q) # ERGO explain this beast; hide inside assert_js_* # FIXME test this with an &entity;! xml = eval('"' + q + '"') xml = '<html><body>' + CGI::unescapeHTML(xml) + '</body></html>' if using :libxml? assert_xml xml # ERGO what are the errors if these fail? end |
#assert_json(jsonic = @xdoc || assert_javascript, diagnostic = nil) ⇒ Object
%html <a name=‘assert_json’></a> Converts a REXML::Element into a Hash containing named elements. Currently we only support Booleans or Strings
This depend on methods like assert_js_argument to locate a JSON argument. Otherwise, the method searches for the first JSON it finds in the current context
-
jsonic
- the input REXML::Element node - defaults to the secret@xdoc
variable set byassert_javascript
.
Example:
%transclude AssertJavaScriptTest#test_assert_json
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/assert_javascript.rb', line 165 def assert_json(jsonic = @xdoc || assert_javascript, diagnostic = nil) @xdoc or assert_javascript returning Hash.new do |json| stash_xdoc do @xdoc = jsonic assert_any_xpath 'descendant-or-self::PropertyNameAndValueList/PropertyPair', diagnostic end # ERGO use assert_any_xpath jsonic.each_element('descendant-or-self::PropertyNameAndValueList/PropertyPair') do |node| name = node.get_path('PropertyName/*') name = name.text.to_sym json[name] = case when b = node.get_path('ObjectLiteral/PropertyNameAndValueList') assert_json(b) when b = node.get_path('Boolean') b.text == '1' when b = node.get_path('Number') b.text # ERGO how to do an or in an XPath?? when b = node.get_path('String') b.text when b = node.get_path('Identifier') b.text # ERGO test me! when b = node.get_path('ArrayLiteral/ElementList') # ERGO recurse here returning [] do |list| b.each_element('*') do |item| list << item.text # ERGO more accurate end end else # ERGO handle embedded JS expressons! #puts indent_xml(node) # ERGO flunk "Add type #{node.children.last.name} to assert_json!" end end end end |
#assert_uri(uri) ⇒ Object
Not ready for public use yet!
239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/assert_javascript.rb', line 239 def assert_uri(uri) path, query = uri.split('?') params = {} if query splitter = using(:libxml?) ? '&' : '&' query.split(splitter).each do |item| key, value = item.split('=') params[key.to_sym] = CGI::unescape(value || '') end end return [path, params] end |
#deny_javascript(source = nil, diagnostic = nil) ⇒ Object Also known as: deny_js
Negates assert_javascript
. Inexplicably passes if a string does not contain anything which satisfies Javascript::PurePerl
‘s narrow definition of JavaScript. Depends on assert_javascript
-
source
- optional string that should not contain JavaScript. The default is @response.body -
diagnostic
- optional string to add to failure message
Note that “var = 2” will pass, (and fail in assert_javascript
) because Javascript::PurePerl
requires a trailing ;
Example: The author would be interested to hear if anyone finds a use for this
127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/assert_javascript.rb', line 127 def deny_javascript(source = nil, diagnostic = nil) javascript_to_xml(source, diagnostic) do stash_xdoc do deny_xpath( '/AST/Program/SourceElements', ( diagnostic, "string <#{_esc source}> should not be well-formed JavaScript" ) ) end end end |
#deny_js_argument(index = 1, diagnostic = nil) ⇒ Object
231 232 233 234 235 |
# File 'lib/assert_javascript.rb', line 231 def deny_js_argument(index = 1, diagnostic = nil) @xdoc or assert_javascript # ERGO rdoc: what do we depend on? deny_xpath xpath_argument(index), diagnostic end |
#deny_js_call(*args) ⇒ Object
-
++ -
-
diagnostic
- optional string to add to failure message
Example:
420 421 422 423 424 |
# File 'lib/assert_javascript.rb', line 420 def deny_js_call(*args) path, arg1, arg2, diagnostic = calling_js_path(args) # ERGO do something with arg1 and arg2 deny_xpath path, diagnostic end |
#deny_js_if(condition = :all, matcher = nil, diagnostic = nil) ⇒ Object
Fails if a JavaScript if
expression or block has the given characteristics
-
*args - ERGO!
-
diagnostic
- optional string to add to failure message
Example:
458 459 460 461 462 463 |
# File 'lib/assert_javascript.rb', line 458 def deny_js_if(condition = :all, matcher = nil, diagnostic = nil) xpath, matcher, diagnostic = _re_arg_if(condition, matcher, diagnostic) return deny_xpath(xpath, diagnostic) unless matcher return deny_any_xpath(xpath, matcher, diagnostic) # ERGO flunk here - with param explanation (if humanly possible!) end |
#deny_js_replace_html(element_id, matcher = nil, diagnostic = nil) ⇒ Object
Negates assert_js_replace_html
-
element_id
- first argument toreplace_html
- the target HTML Element’sid
-
matcher
- optional regular expression to not match the raw contents of the second argument toreplace_html
-
diagnostic
- optional string to add to failure message
If the matcher
is nil
or not provided, the element_id
must /not/ match any Element.update
call in its context. If the matcher
/is/ provided, the element_id
/must/ match, and the matcher
must /not/ agree with its contents
Example: AssertJavaScriptTest#test_deny_js_replace_html
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/assert_javascript.rb', line 294 def deny_js_replace_html(element_id, matcher = nil, diagnostic = nil) path = object_method_xpath('Element', 'update', element_id) # ERGO don't let subsequent updates with the same element_id confuse the matcher! if matcher and node = @xdoc.get_path(path) stash_xdoc do @xdoc = node assert_no_match matcher, assert_js_argument(2), diagnostic return # ERGO pass node for 1st arg to assert_js_argument end end deny_xpath path, diagnostic end |
#returning(value) {|value| ... } ⇒ Object
:nodoc:
142 143 144 145 |
# File 'lib/assert_javascript.rb', line 142 def returning(value) #:nodoc: yield(value) return value end |