Skip to content

Commit

Permalink
Browser: Added EVENTS_PER_ELEMENT hash
Browse files Browse the repository at this point in the history
[Issue #50]
  • Loading branch information
Zapotek committed Aug 27, 2013
1 parent 679139a commit fbd5673
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 33 deletions.
98 changes: 65 additions & 33 deletions lib/arachni/browser.rb
Expand Up @@ -40,6 +40,7 @@ class Load < Error
end
end

# Events that apply to all elements.
GLOBAL_EVENTS = [
:onclick,
:ondblclick,
Expand All @@ -50,9 +51,59 @@ class Load < Error
:onmouseup
]

# Special events for each element.
EVENTS_PER_ELEMENT = {
body: [
:onload
],

form: [
:onsubmit,
:onreset
],

# These need to be covered via Watir's API, #send_keys etc.
input: [
:onselect,
:onchange,
:onfocus,
:onblur,
:onkeydown,
:onkeypress,
:onkeyup
],

# These need to be covered via Watir's API, #send_keys etc.
textarea: [
:onselect,
:onchange,
:onfocus,
:onblur,
:onkeydown,
:onkeypress,
:onkeyup
],

select: [
:onchange,
:onfocus,
:onblur
],

button: [
:onfocus,
:onblur
],

label: [
:onfocus,
:onblur
]
}

NO_EVENTS_FOR_ELEMENTS = Set.new([
:base, :bdo, :br, :head, :html, :iframe, :meta, :param, :script,
:style, :title, :link, :script
:base, :bdo, :br, :head, :html, :iframe, :meta, :param, :script, :style,
:title, :link, :script
])

# @return [Hash] Preloaded resources, by URL.
Expand All @@ -68,6 +119,10 @@ def self.has_executable?
@has_executable = !!Selenium::WebDriver::PhantomJS.path
end

def self.events
Browser::GLOBAL_EVENTS | Browser::EVENTS_PER_ELEMENT.values.flatten.uniq
end

# @param [Hash] options
# @option options [Integer] :timeout (5)
# Max time to wait for the page to settle (for pending AJAX requests etc).
Expand Down Expand Up @@ -336,7 +391,7 @@ def trigger_events
root_page = to_page

while (info = pending.shift) do
events_to_trigger_for( info[:tag_name] ).each do |event|
events_for( info[:tag_name] ).each do |event|
distribute_event( root_page, info[:index], event )
end
end
Expand Down Expand Up @@ -593,36 +648,6 @@ def wait_for_pending_requests
false
end

def events_to_trigger_for( tag_name )
tag_name = tag_name.to_sym
return [] if NO_EVENTS_FOR_ELEMENTS.include?( tag_name )

case tag_name
when :body
[:onload]

when :form
[:onsubmit, :onreset]

# These need to be covered via Watir's API, #send_keys etc.
when :input, :textarea
[:onselect, :onchange, :onfocus, :onblur, :onkeydown,
:onkeypress, :onkeyup]

when :select
[:onchange, :onfocus, :onblur]

when :button
[:onfocus, :onblur]

when :label
[:onfocus, :onblur]

else
[]
end + GLOBAL_EVENTS
end

def load_cookies( url )
# First clears the browser's cookies and then tricks it into accepting
# the system cookies for its cookie-jar.
Expand Down Expand Up @@ -663,6 +688,13 @@ def capabilities
)
end

def events_for( tag_name )
tag_name = tag_name.to_sym
return [] if NO_EVENTS_FOR_ELEMENTS.include?( tag_name )

(EVENTS_PER_ELEMENT[tag_name] || []) + GLOBAL_EVENTS
end

def flush_request_transitions
@request_transitions.dup
ensure
Expand Down
39 changes: 39 additions & 0 deletions spec/arachni/browser_spec.rb
Expand Up @@ -65,6 +65,30 @@ def pages_should_not_have_form_with_input( pages, input_name )
pages_should_not_have_form_with_input pages, 'by-ajax'
end

describe '.events' do
it 'returns all DOM events' do
described_class.events.sort.should == [
:onclick,
:ondblclick,
:onmousedown,
:onmousemove,
:onmouseout,
:onmouseover,
:onmouseup,
:onload,
:onsubmit,
:onreset,
:onselect,
:onchange,
:onfocus,
:onblur,
:onkeydown,
:onkeypress,
:onkeyup
].sort
end
end

describe '#initialize' do
describe :store_pages do
describe 'default' do
Expand Down Expand Up @@ -271,6 +295,21 @@ def pages_should_not_have_form_with_input( pages, input_name )
end
end

describe '#trigger_event' do
it 'triggers the given event' do
@browser.load( @url + '/trigger_events' ).start_capture

@browser.watir.elements.each.with_index do |_, index|
described_class.events.each do |e|
@browser.trigger_event @browser.to_page, index, e
end
end

pages_should_have_form_with_input @browser.page_snapshots, 'by-ajax'
pages_should_have_form_with_input @browser.captured_pages, 'ajax-token'
end
end

describe '#trigger_events' do
it 'waits for AJAX requests to complete' do
@browser.load( @url + '/trigger_events-wait-for-ajax' ).start_capture.trigger_events
Expand Down

0 comments on commit fbd5673

Please sign in to comment.