watir-classic 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +721 -0
- data/LICENSE +34 -0
- data/README.rdoc +78 -0
- data/VERSION +1 -0
- data/bin/watir-console +5 -0
- data/lib/watir-classic.rb +14 -0
- data/lib/watir-classic/IEDialog/Release/IEDialog.dll +0 -0
- data/lib/watir-classic/assertions.rb +44 -0
- data/lib/watir-classic/browser.rb +149 -0
- data/lib/watir-classic/browsers.rb +7 -0
- data/lib/watir-classic/close_all.rb +31 -0
- data/lib/watir-classic/container.rb +110 -0
- data/lib/watir-classic/contrib/enabled_popup.rb +21 -0
- data/lib/watir-classic/contrib/ie-new-process.rb +27 -0
- data/lib/watir-classic/contrib/page_checker.rb +29 -0
- data/lib/watir-classic/cookies.rb +80 -0
- data/lib/watir-classic/core.rb +43 -0
- data/lib/watir-classic/dialogs/file_field.rb +34 -0
- data/lib/watir-classic/dialogs/javascript.rb +43 -0
- data/lib/watir-classic/drag_and_drop_helper.rb +68 -0
- data/lib/watir-classic/element.rb +438 -0
- data/lib/watir-classic/element_collection.rb +109 -0
- data/lib/watir-classic/element_extensions.rb +69 -0
- data/lib/watir-classic/exceptions.rb +50 -0
- data/lib/watir-classic/form.rb +96 -0
- data/lib/watir-classic/frame.rb +47 -0
- data/lib/watir-classic/ie-class.rb +767 -0
- data/lib/watir-classic/ie-process.rb +47 -0
- data/lib/watir-classic/ie.rb +20 -0
- data/lib/watir-classic/image.rb +111 -0
- data/lib/watir-classic/input_elements.rb +480 -0
- data/lib/watir-classic/irb-history.rb +31 -0
- data/lib/watir-classic/link.rb +46 -0
- data/lib/watir-classic/locator.rb +243 -0
- data/lib/watir-classic/logger.rb +19 -0
- data/lib/watir-classic/matches.rb +23 -0
- data/lib/watir-classic/modal_dialog.rb +72 -0
- data/lib/watir-classic/module.rb +12 -0
- data/lib/watir-classic/non_control_elements.rb +114 -0
- data/lib/watir-classic/options.rb +56 -0
- data/lib/watir-classic/page-container.rb +114 -0
- data/lib/watir-classic/process.rb +20 -0
- data/lib/watir-classic/screen_capture.rb +115 -0
- data/lib/watir-classic/supported_elements.rb +172 -0
- data/lib/watir-classic/table.rb +224 -0
- data/lib/watir-classic/testcase.rb +97 -0
- data/lib/watir-classic/util.rb +35 -0
- data/lib/watir-classic/version.rb +4 -0
- data/lib/watir-classic/wait.rb +41 -0
- data/lib/watir-classic/wait_helper.rb +12 -0
- data/lib/watir-classic/waiter.rb +98 -0
- data/lib/watir-classic/win32.rb +40 -0
- data/lib/watir-classic/win32ole.rb +16 -0
- data/lib/watir-classic/win32ole/1.8.7/win32ole.so +0 -0
- data/lib/watir-classic/win32ole/1.9.3/win32ole.so +0 -0
- data/lib/watir-classic/window.rb +68 -0
- data/lib/watir-classic/xpath_locator.rb +52 -0
- data/rakefile.rb +54 -0
- data/unittests/all_tests.rb +10 -0
- data/unittests/buttons_xpath_test.rb +68 -0
- data/unittests/checkbox_test.rb +163 -0
- data/unittests/checkbox_xpath_test.rb +106 -0
- data/unittests/click_no_wait_test.rb +23 -0
- data/unittests/close_all_test.rb +17 -0
- data/unittests/core_tests.rb +17 -0
- data/unittests/css_selector_test.rb +44 -0
- data/unittests/css_test.rb +38 -0
- data/unittests/dialog_test.rb +64 -0
- data/unittests/div2_xpath_test.rb +21 -0
- data/unittests/div_test.rb +170 -0
- data/unittests/div_xpath_test.rb +95 -0
- data/unittests/document_standards.rb +63 -0
- data/unittests/element_collection_indexes_test.rb +57 -0
- data/unittests/element_collections_test.rb +100 -0
- data/unittests/element_test.rb +47 -0
- data/unittests/errorchecker_test.rb +31 -0
- data/unittests/filefield_test.rb +43 -0
- data/unittests/filefield_xpath_test.rb +35 -0
- data/unittests/form_test.rb +282 -0
- data/unittests/form_xpath_test.rb +254 -0
- data/unittests/frame_test.rb +165 -0
- data/unittests/google_form_test.rb +15 -0
- data/unittests/html/JavascriptClick.html +39 -0
- data/unittests/html/blankpage.html +11 -0
- data/unittests/html/buttons1.html +40 -0
- data/unittests/html/checkboxes1.html +89 -0
- data/unittests/html/click_no_wait.html +14 -0
- data/unittests/html/complex_table.html +35 -0
- data/unittests/html/cssTest.html +42 -0
- data/unittests/html/depot_store.html +59 -0
- data/unittests/html/div.html +92 -0
- data/unittests/html/div_xml.html +21 -0
- data/unittests/html/fileupload.html +44 -0
- data/unittests/html/formTest1.html +38 -0
- data/unittests/html/forms2.html +44 -0
- data/unittests/html/forms3.html +131 -0
- data/unittests/html/forms4.html +26 -0
- data/unittests/html/frame_buttons.html +4 -0
- data/unittests/html/frame_links.html +4 -0
- data/unittests/html/frame_multi.html +5 -0
- data/unittests/html/google_india.html +119 -0
- data/unittests/html/ie7_document_standards.html +9 -0
- data/unittests/html/ie8_document_standards.html +9 -0
- data/unittests/html/ie9_document_standards.html +9 -0
- data/unittests/html/iframe.html +3 -0
- data/unittests/html/iframeTest.html +17 -0
- data/unittests/html/iframeTest1.html +7 -0
- data/unittests/html/iframeTest2.html +5 -0
- data/unittests/html/images/1.gif +0 -0
- data/unittests/html/images/2.GIF +0 -0
- data/unittests/html/images/3.GIF +0 -0
- data/unittests/html/images/button.jpg +0 -0
- data/unittests/html/images/circle.jpg +0 -0
- data/unittests/html/images/map.GIF +0 -0
- data/unittests/html/images/map2.gif +0 -0
- data/unittests/html/images/minus.GIF +0 -0
- data/unittests/html/images/originaltriangle.jpg +0 -0
- data/unittests/html/images/plus.gif +0 -0
- data/unittests/html/images/square.jpg +0 -0
- data/unittests/html/images/triangle.jpg +0 -0
- data/unittests/html/images1.html +65 -0
- data/unittests/html/javascriptevents.html +33 -0
- data/unittests/html/link_pass.html +11 -0
- data/unittests/html/links1.html +37 -0
- data/unittests/html/links2.html +11 -0
- data/unittests/html/links_multi.html +12 -0
- data/unittests/html/list_matters.html +720 -0
- data/unittests/html/lists.html +18 -0
- data/unittests/html/map_test.html +30 -0
- data/unittests/html/modal_dialog.html +10 -0
- data/unittests/html/modal_dialog_launcher.html +12 -0
- data/unittests/html/multiple_specifiers.html +64 -0
- data/unittests/html/nestedFrames.html +6 -0
- data/unittests/html/new_browser.html +17 -0
- data/unittests/html/pass.html +13 -0
- data/unittests/html/popups1.html +59 -0
- data/unittests/html/pre.html +29 -0
- data/unittests/html/quirks_document_standards.html +8 -0
- data/unittests/html/radioButtons1.html +71 -0
- data/unittests/html/select_tealeaf.html +54 -0
- data/unittests/html/selectboxes1.html +52 -0
- data/unittests/html/simple_table.html +25 -0
- data/unittests/html/simple_table_buttons.html +104 -0
- data/unittests/html/simple_table_columns.html +75 -0
- data/unittests/html/table1.html +179 -0
- data/unittests/html/tableCell_using_xpath.html +19 -0
- data/unittests/html/table_and_tablerow_to_a.html +174 -0
- data/unittests/html/textarea.html +30 -0
- data/unittests/html/textfields1.html +100 -0
- data/unittests/html/textsearch.html +44 -0
- data/unittests/html/wallofcheckboxes.html +1003 -0
- data/unittests/html/xpath_nbsp.html +11 -0
- data/unittests/html/zeroindex.html +11 -0
- data/unittests/ie_exists_test.rb +16 -0
- data/unittests/ie_mock.rb +94 -0
- data/unittests/ie_test.rb +54 -0
- data/unittests/images_test.rb +156 -0
- data/unittests/images_xpath_test.rb +90 -0
- data/unittests/index_specifier_test.rb +31 -0
- data/unittests/js_events_test.rb +31 -0
- data/unittests/links_multi_test.rb +34 -0
- data/unittests/links_test.rb +131 -0
- data/unittests/links_xpath_test.rb +38 -0
- data/unittests/lists_test.rb +23 -0
- data/unittests/map_test.rb +98 -0
- data/unittests/minmax_test.rb +37 -0
- data/unittests/navigate_test.rb +38 -0
- data/unittests/nbsp_xpath_test.rb +16 -0
- data/unittests/no_wait_test.rb +28 -0
- data/unittests/non_core_tests.rb +12 -0
- data/unittests/other/all_tests_concurrent.rb +57 -0
- data/unittests/other/navigate_exception_test.rb +24 -0
- data/unittests/other/rexml_unit_test.rb +27 -0
- data/unittests/other/screen_capture_test.rb +53 -0
- data/unittests/other/testcase_method_order_test.rb +36 -0
- data/unittests/other/testcase_verify_test.rb +25 -0
- data/unittests/other/wait_until_test.rb +102 -0
- data/unittests/pagecontainstext_test.rb +69 -0
- data/unittests/parent_child_test.rb +27 -0
- data/unittests/perf_test.rb +20 -0
- data/unittests/pre_test.rb +49 -0
- data/unittests/radios_test.rb +181 -0
- data/unittests/radios_xpath_test.rb +100 -0
- data/unittests/security_setting_test.rb +24 -0
- data/unittests/selectbox_test.rb +144 -0
- data/unittests/selectbox_xpath_test.rb +102 -0
- data/unittests/setup.rb +69 -0
- data/unittests/speed_settings_test.rb +67 -0
- data/unittests/table_cell_using_xpath_test.rb +34 -0
- data/unittests/table_test.rb +296 -0
- data/unittests/table_xpath_test.rb +109 -0
- data/unittests/test_tests.rb +9 -0
- data/unittests/textarea_test.rb +92 -0
- data/unittests/textarea_xpath_test.rb +77 -0
- data/unittests/textfield_for_ch_char_test.rb +32 -0
- data/unittests/textfields_test.rb +184 -0
- data/unittests/textfields_xpath_test.rb +110 -0
- data/unittests/version_test.rb +15 -0
- data/unittests/win32ole_so_test.rb +35 -0
- data/unittests/window_tests.rb +10 -0
- data/unittests/windows/attach_to_existing_window_test.rb +52 -0
- data/unittests/windows/attach_to_new_window_test.rb +74 -0
- data/unittests/windows/close_window_test.rb +20 -0
- data/unittests/windows/frame_links_test.rb +23 -0
- data/unittests/windows/ie-each_test.rb +46 -0
- data/unittests/windows/modal_dialog_test.rb +95 -0
- data/unittests/windows/new_process_test.rb +24 -0
- data/unittests/windows/new_test.rb +58 -0
- data/unittests/windows/open_close_test.rb +19 -0
- data/unittests/windows/send_keys_test.rb +26 -0
- data/unittests/xpath_tests.rb +11 -0
- data/watir-rdoc.rb +7 -0
- metadata +370 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# http://www.vbcity.com/forums/topic.asp?tid=108859
|
|
2
|
+
require 'watir-classic/ie'
|
|
3
|
+
module Watir
|
|
4
|
+
module PageContainer
|
|
5
|
+
include Win32
|
|
6
|
+
def enabled_popup(timeout=4)
|
|
7
|
+
# Use handle of our parent window to see if we have any currently
|
|
8
|
+
# enabled popup.
|
|
9
|
+
hwnd_modal = 0
|
|
10
|
+
Wait.until(timeout) do
|
|
11
|
+
hwnd_modal, arr = GetWindow.call(hwnd, GW_ENABLEDPOPUP)
|
|
12
|
+
hwnd_modal > 0
|
|
13
|
+
end
|
|
14
|
+
# use hwnd() method to find the IE or Container hwnd (overriden by IE)
|
|
15
|
+
if hwnd_modal == hwnd() || 0 == hwnd_modal
|
|
16
|
+
hwnd_modal = nil
|
|
17
|
+
end
|
|
18
|
+
hwnd_modal
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# based on http://svn.instiki.org/instiki/trunk/test/watir/e2e.rb
|
|
2
|
+
# and http://rubyforge.org/pipermail/wtr-general/2005-November/004108.html
|
|
3
|
+
|
|
4
|
+
require 'watir-classic/ie-process'
|
|
5
|
+
|
|
6
|
+
class IEProcess < Watir::IE::Process
|
|
7
|
+
def stop
|
|
8
|
+
right_to_terminate_process = 1
|
|
9
|
+
handle = Win32API.new('kernel32.dll', 'OpenProcess', 'lil', 'l').
|
|
10
|
+
call(right_to_terminate_process, 0, @process_id)
|
|
11
|
+
Win32API.new('kernel32.dll', 'TerminateProcess', 'll', 'l').call(handle, 0)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module Watir
|
|
17
|
+
class IE
|
|
18
|
+
def process_id
|
|
19
|
+
@process_id ||= IEProcess.process_id_from_hwnd @ie.hwnd
|
|
20
|
+
end
|
|
21
|
+
attr_writer :process_id
|
|
22
|
+
def kill
|
|
23
|
+
iep = IEProcess.new process_id
|
|
24
|
+
iep.stop
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# This module includes checkers which are run on every page load
|
|
2
|
+
#
|
|
3
|
+
# In order to use this module, add a require to one of your test scripts:
|
|
4
|
+
# require 'watir-classic/contrib/page_checker'
|
|
5
|
+
# To add checkers, call the ie.add_checker method
|
|
6
|
+
#
|
|
7
|
+
# ie.add_checker(PageCheckers::NAVIGATION_CHECKER)
|
|
8
|
+
#
|
|
9
|
+
# Checkers are Ruby proc objects which are called within Watir::IE and passed
|
|
10
|
+
# the current instance of ie.
|
|
11
|
+
|
|
12
|
+
module PageCheckers
|
|
13
|
+
|
|
14
|
+
# This checker iterates through the current document including any frames
|
|
15
|
+
# and checks for http errors, 404, 500 etc
|
|
16
|
+
NAVIGATION_CHECKER = lambda do |ie|
|
|
17
|
+
if ie.document.frames.length > 1
|
|
18
|
+
1.upto ie.document.frames.length do |i|
|
|
19
|
+
begin
|
|
20
|
+
ie.frame(:index, i).check_for_http_error
|
|
21
|
+
rescue Watir::Exception::UnknownFrameException
|
|
22
|
+
# frame can be already destroyed
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
else
|
|
26
|
+
ie.check_for_http_error
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require "uri"
|
|
2
|
+
|
|
3
|
+
module Watir
|
|
4
|
+
class Cookies
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
def initialize(page_container)
|
|
8
|
+
@page_container = page_container
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def each
|
|
12
|
+
@page_container.document.cookie.split(";").each do |cookie|
|
|
13
|
+
name, value = cookie.strip.split("=")
|
|
14
|
+
yield({:name => name, :value => value})
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def add name, value, options={}
|
|
19
|
+
options = options.map do |option|
|
|
20
|
+
k, v = option
|
|
21
|
+
if k == :expires
|
|
22
|
+
"#{k}=#{v.gmtime.strftime("%a, %d %b %Y %H:%M:%S UTC")}"
|
|
23
|
+
elsif k == :secure
|
|
24
|
+
"secure" if v
|
|
25
|
+
else
|
|
26
|
+
"#{k}=#{v}"
|
|
27
|
+
end
|
|
28
|
+
end.compact.join("; ")
|
|
29
|
+
|
|
30
|
+
options = "; #{options}" unless options.empty?
|
|
31
|
+
@page_container.document.cookie = "#{name}=#{value}#{options}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def delete name
|
|
35
|
+
options = {:expires => ::Time.now - 60 * 60 * 24}
|
|
36
|
+
delete_with_options name, options
|
|
37
|
+
|
|
38
|
+
# make sure that the cookie gets deleted
|
|
39
|
+
# there's got to be some easier way to do this
|
|
40
|
+
uri = URI.parse(@page_container.url)
|
|
41
|
+
domain = uri.host
|
|
42
|
+
|
|
43
|
+
paths = uri.path.split("/").reduce([]) do |paths, path|
|
|
44
|
+
paths << "#{paths.last}/#{path}".squeeze("/")
|
|
45
|
+
end << "/"
|
|
46
|
+
|
|
47
|
+
subdomains = domain.split(".").reverse.reduce([]) do |subdomains, part|
|
|
48
|
+
subdomain = "#{part}#{subdomains.last}"
|
|
49
|
+
subdomain = "." + subdomain unless subdomain == domain
|
|
50
|
+
subdomains << subdomain
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
subdomains.each do |subdomain|
|
|
54
|
+
domain_options = options.merge :domain => subdomain
|
|
55
|
+
delete_with_options name, domain_options
|
|
56
|
+
delete_with_options name, domain_options.merge(:secure => true)
|
|
57
|
+
|
|
58
|
+
paths.each do |path|
|
|
59
|
+
path_options = options.merge :path => path
|
|
60
|
+
delete_with_options name, path_options
|
|
61
|
+
delete_with_options name, path_options.merge(:secure => true)
|
|
62
|
+
|
|
63
|
+
path_domain_options = domain_options.merge :path => path
|
|
64
|
+
delete_with_options name, path_domain_options
|
|
65
|
+
delete_with_options name, path_domain_options.merge(:secure => true)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def clear
|
|
71
|
+
each {|cookie| delete cookie[:name]}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def delete_with_options name, options={}
|
|
75
|
+
add name, nil, options
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private :delete_with_options
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# these require statements are needed for Watir
|
|
2
|
+
# to work with minimum functionality
|
|
3
|
+
require 'timeout'
|
|
4
|
+
require 'watir-classic/win32ole'
|
|
5
|
+
|
|
6
|
+
# these are required already in commonwatir-classic, but not when using click_no_wait!
|
|
7
|
+
require 'watir-classic/util'
|
|
8
|
+
require 'watir-classic/exceptions'
|
|
9
|
+
require 'watir-classic/matches'
|
|
10
|
+
require 'watir-classic/wait'
|
|
11
|
+
require 'watir-classic/wait_helper'
|
|
12
|
+
require 'watir-classic/element_extensions'
|
|
13
|
+
|
|
14
|
+
require 'logger'
|
|
15
|
+
require 'watir-classic/logger'
|
|
16
|
+
require 'watir-classic/container'
|
|
17
|
+
require 'watir-classic/xpath_locator'
|
|
18
|
+
require 'watir-classic/locator'
|
|
19
|
+
require 'watir-classic/page-container'
|
|
20
|
+
require 'watir-classic/ie-class'
|
|
21
|
+
require 'watir-classic/drag_and_drop_helper'
|
|
22
|
+
require 'watir-classic/element'
|
|
23
|
+
require 'watir-classic/element_collection'
|
|
24
|
+
require 'watir-classic/form'
|
|
25
|
+
require 'watir-classic/frame'
|
|
26
|
+
require 'watir-classic/input_elements'
|
|
27
|
+
require 'watir-classic/non_control_elements'
|
|
28
|
+
require 'watir-classic/table'
|
|
29
|
+
require 'watir-classic/image'
|
|
30
|
+
require 'watir-classic/link'
|
|
31
|
+
require 'watir-classic/window'
|
|
32
|
+
require 'watir-classic/cookies'
|
|
33
|
+
|
|
34
|
+
require 'watir-classic/win32'
|
|
35
|
+
require 'watir-classic/modal_dialog'
|
|
36
|
+
|
|
37
|
+
require 'watir-classic/module'
|
|
38
|
+
|
|
39
|
+
require 'rautomation'
|
|
40
|
+
require 'watir-classic/dialogs/file_field'
|
|
41
|
+
require 'watir-classic/dialogs/javascript'
|
|
42
|
+
|
|
43
|
+
require 'watir-classic/supported_elements'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Watir
|
|
2
|
+
class FileField < InputElement
|
|
3
|
+
def set(file_path)
|
|
4
|
+
assert_file_exists(file_path)
|
|
5
|
+
assert_exists
|
|
6
|
+
click_no_wait
|
|
7
|
+
set_file_name file_path.gsub(File::SEPARATOR, File::ALT_SEPARATOR)
|
|
8
|
+
open_button.click
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
alias_method :value=, :set
|
|
12
|
+
|
|
13
|
+
def assert_file_exists(file_path)
|
|
14
|
+
raise Errno::ENOENT, "#{file_path} has to exist to set!" unless File.exists?(file_path)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def set_file_name(path_to_file)
|
|
18
|
+
file_upload_window.text_field(:class => 'Edit', :index => 0).set path_to_file
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def open_button
|
|
22
|
+
file_upload_window.button(:value => /&Open|&Abrir/)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def cancel_button
|
|
26
|
+
file_upload_window.button(:value => /Cancel/)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def file_upload_window
|
|
30
|
+
@window ||= RAutomation::Window.new(:title => /^choose file( to upload)?|Elegir archivos para cargar$/i)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Watir
|
|
2
|
+
|
|
3
|
+
class JavascriptDialog
|
|
4
|
+
WINDOW_TITLES = ['Message from webpage', 'Windows Internet Explorer','Microsoft Internet Explorer',/Mensaje de p.*/]
|
|
5
|
+
|
|
6
|
+
def initialize(opts={})
|
|
7
|
+
@opts = opts
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def exists?
|
|
11
|
+
javascript_dialog_window.exists?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def button(value)
|
|
15
|
+
javascript_dialog_window.button(:value => value)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def close
|
|
19
|
+
javascript_dialog_window.close
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def text
|
|
23
|
+
javascript_dialog_window.text
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def javascript_dialog_window
|
|
27
|
+
@window ||= ::RAutomation::Window.new(:title => @opts[:title] || /^(#{WINDOW_TITLES.join('|')})$/)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Watir::Container.module_eval do
|
|
31
|
+
def javascript_dialog(opts={})
|
|
32
|
+
JavascriptDialog.new(opts)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
alias_method :dialog, :javascript_dialog
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Watir
|
|
2
|
+
module DragAndDropHelper
|
|
3
|
+
|
|
4
|
+
def drag_and_drop_on(target)
|
|
5
|
+
perform_action do
|
|
6
|
+
assert_target target
|
|
7
|
+
drop_x, drop_y = target.send :source_x_y
|
|
8
|
+
drag_to drop_x, drop_y
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def drag_and_drop_by(distance_x, distance_y)
|
|
13
|
+
perform_action do
|
|
14
|
+
drag_x, drag_y = source_x_y
|
|
15
|
+
drag_to drag_x + distance_x, drag_y + distance_y
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def drag_to(drop_x, drop_y)
|
|
22
|
+
drag_x, drag_y = source_x_y
|
|
23
|
+
mouse = page_container.rautomation.mouse
|
|
24
|
+
mouse.move :x => drag_x , :y => drag_y
|
|
25
|
+
mouse.press
|
|
26
|
+
mouse.move :x => drop_x, :y => drop_y
|
|
27
|
+
mouse.release
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def source_x_y
|
|
31
|
+
center_x_y_absolute left_edge_absolute, top_edge_absolute
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def assert_target(target)
|
|
35
|
+
target.assert_exists
|
|
36
|
+
target.assert_enabled
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def top_edge
|
|
40
|
+
ole_object.getBoundingClientRect(0).top.to_i
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def top_edge_absolute
|
|
44
|
+
top_edge + page_container.document.parentWindow.screenTop.to_i
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def left_edge
|
|
48
|
+
ole_object.getBoundingClientRect(0).left.to_i
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def left_edge_absolute
|
|
52
|
+
left_edge + page_container.document.parentWindow.screenLeft.to_i
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def right_edge
|
|
56
|
+
ole_object.getBoundingClientRect(0).right.to_i
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def bottom_edge
|
|
60
|
+
ole_object.getBoundingClientRect(0).bottom.to_i
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def center_x_y_absolute x, y
|
|
64
|
+
return (right_edge - left_edge) / 2 + x, (bottom_edge - top_edge) / 2 + y
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
module Watir
|
|
2
|
+
# Base class for html elements.
|
|
3
|
+
# This is not a class that users would normally access.
|
|
4
|
+
class Element # Wrapper
|
|
5
|
+
include Comparable
|
|
6
|
+
include ElementExtensions
|
|
7
|
+
include Exception
|
|
8
|
+
include Container # presumes @container is defined
|
|
9
|
+
include DragAndDropHelper
|
|
10
|
+
|
|
11
|
+
attr_accessor :container
|
|
12
|
+
|
|
13
|
+
# number of spaces that separate the property from the value in the to_s method
|
|
14
|
+
TO_S_SIZE = 14
|
|
15
|
+
|
|
16
|
+
def initialize(container, specifiers)
|
|
17
|
+
set_container container
|
|
18
|
+
raise ArgumentError, "#{specifiers.inspect} has to be Hash" unless specifiers.is_a?(Hash)
|
|
19
|
+
|
|
20
|
+
@o = specifiers[:ole_object]
|
|
21
|
+
@specifiers = specifiers
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def <=> other
|
|
25
|
+
assert_exists
|
|
26
|
+
other.assert_exists
|
|
27
|
+
ole_object.sourceindex <=> other.ole_object.sourceindex
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
alias_method :eql?, :==
|
|
31
|
+
|
|
32
|
+
def locate
|
|
33
|
+
@o = @container.locator_for(TaggedElementLocator, @specifiers, self.class).locate
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Return the ole object, allowing any methods of the DOM that Watir doesn't support to be used.
|
|
37
|
+
def ole_object
|
|
38
|
+
@o
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ole_object=(o)
|
|
42
|
+
@o = o
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def inspect
|
|
46
|
+
'#<%s:0x%x located=%s specifiers=%s>' % [self.class, hash*2, !!ole_object, @specifiers.inspect]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def self.attr_ole(method_name, ole_method_name=nil)
|
|
52
|
+
class_eval %Q[
|
|
53
|
+
def #{method_name}
|
|
54
|
+
assert_exists
|
|
55
|
+
ole_method_name = '#{ole_method_name || method_name.to_s.gsub(/\?$/, '')}'
|
|
56
|
+
ole_object.invoke(ole_method_name) rescue attribute_value(ole_method_name) || '' rescue ''
|
|
57
|
+
end]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
public
|
|
61
|
+
|
|
62
|
+
def assert_exists
|
|
63
|
+
locate
|
|
64
|
+
unless ole_object
|
|
65
|
+
exception_class = self.is_a?(Frame) ? UnknownFrameException : UnknownObjectException
|
|
66
|
+
raise exception_class.new(Watir::Exception.message_for_unable_to_locate(@specifiers))
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def assert_enabled
|
|
71
|
+
raise ObjectDisabledException, "object #{@specifiers.inspect} is disabled" unless enabled?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# return the id of the element
|
|
75
|
+
attr_ole :id
|
|
76
|
+
# return the title of the element
|
|
77
|
+
attr_ole :title
|
|
78
|
+
# return the class name of the element
|
|
79
|
+
# raise an ObjectNotFound exception if the object cannot be found
|
|
80
|
+
attr_ole :class_name, :className
|
|
81
|
+
# return the unique COM number for the element
|
|
82
|
+
attr_ole :unique_number, :uniqueNumber
|
|
83
|
+
# Return the outer html of the object - see http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/outerhtml.asp?frame=true
|
|
84
|
+
attr_ole :html, :outerHTML
|
|
85
|
+
|
|
86
|
+
def tag_name
|
|
87
|
+
assert_exists
|
|
88
|
+
@o.tagName.downcase
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# returns specific Element subclass for current Element
|
|
92
|
+
def to_subtype
|
|
93
|
+
assert_exists
|
|
94
|
+
|
|
95
|
+
tag = tag_name
|
|
96
|
+
if tag == "html"
|
|
97
|
+
element(:ole_object => ole_object)
|
|
98
|
+
elsif tag == "input"
|
|
99
|
+
send(ole_object.invoke('type'), :ole_object => ole_object)
|
|
100
|
+
elsif tag == "select"
|
|
101
|
+
select_list(:ole_object => ole_object)
|
|
102
|
+
elsif respond_to?(tag.downcase)
|
|
103
|
+
send(tag.downcase, :ole_object => ole_object)
|
|
104
|
+
else
|
|
105
|
+
self
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# send keys to element
|
|
110
|
+
def send_keys(*keys)
|
|
111
|
+
focus
|
|
112
|
+
page_container.send_keys *keys
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# return the css style as a string
|
|
116
|
+
def style
|
|
117
|
+
assert_exists
|
|
118
|
+
ole_object.style.cssText
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Return the innerText of the object or an empty string if the object is
|
|
122
|
+
# not visible
|
|
123
|
+
# Raise an ObjectNotFound exception if the object cannot be found
|
|
124
|
+
def text
|
|
125
|
+
assert_exists
|
|
126
|
+
visible? ? ole_object.innerText.strip : ""
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def __ole_inner_elements
|
|
130
|
+
assert_exists
|
|
131
|
+
ole_object.all
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def document
|
|
135
|
+
assert_exists
|
|
136
|
+
ole_object
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Return the element immediately containing self.
|
|
140
|
+
def parent
|
|
141
|
+
assert_exists
|
|
142
|
+
parent_element = ole_object.parentelement
|
|
143
|
+
return unless parent_element
|
|
144
|
+
Element.new(self, :ole_object => parent_element).to_subtype
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def typingspeed
|
|
148
|
+
@container.typingspeed
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def type_keys
|
|
152
|
+
@type_keys || @container.type_keys
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def activeObjectHighLightColor
|
|
156
|
+
@container.activeObjectHighLightColor
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Return an array with many of the properties, in a format to be used by the to_s method
|
|
160
|
+
def string_creator
|
|
161
|
+
n = []
|
|
162
|
+
n << "id:".ljust(TO_S_SIZE) + self.id.to_s
|
|
163
|
+
return n
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
private :string_creator
|
|
167
|
+
|
|
168
|
+
# Display basic details about the object. Sample output for a button is shown.
|
|
169
|
+
# Raises UnknownObjectException if the object is not found.
|
|
170
|
+
# name b4
|
|
171
|
+
# type button
|
|
172
|
+
# id b5
|
|
173
|
+
# value Disabled Button
|
|
174
|
+
# disabled true
|
|
175
|
+
def to_s
|
|
176
|
+
assert_exists
|
|
177
|
+
return string_creator.join("\n")
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# This method is responsible for setting and clearing the colored highlighting on the currently active element.
|
|
181
|
+
# use :set to set the highlight
|
|
182
|
+
# :clear to clear the highlight
|
|
183
|
+
# TODO: Make this two methods: set_highlight & clear_highlight
|
|
184
|
+
# TODO: Remove begin/rescue blocks
|
|
185
|
+
def highlight(set_or_clear)
|
|
186
|
+
if set_or_clear == :set
|
|
187
|
+
begin
|
|
188
|
+
@original_color ||= ole_object.style.backgroundColor
|
|
189
|
+
ole_object.style.backgroundColor = @container.activeObjectHighLightColor
|
|
190
|
+
rescue
|
|
191
|
+
@original_color = nil
|
|
192
|
+
end
|
|
193
|
+
else
|
|
194
|
+
begin
|
|
195
|
+
ole_object.style.backgroundColor = @original_color if @original_color
|
|
196
|
+
rescue
|
|
197
|
+
# we could be here for a number of reasons...
|
|
198
|
+
# e.g. page may have reloaded and the reference is no longer valid
|
|
199
|
+
ensure
|
|
200
|
+
@original_color = nil
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
private :highlight
|
|
206
|
+
|
|
207
|
+
# This method clicks the active element.
|
|
208
|
+
# raises: UnknownObjectException if the object is not found
|
|
209
|
+
# ObjectDisabledException if the object is currently disabled
|
|
210
|
+
def click
|
|
211
|
+
click!
|
|
212
|
+
@container.wait
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def right_click
|
|
216
|
+
perform_action {fire_event("oncontextmenu"); @container.wait}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def double_click
|
|
220
|
+
perform_action {fire_event("ondblclick"); @container.wait}
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def replace_method(method)
|
|
224
|
+
method == 'click' ? 'click!' : method
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
private :replace_method
|
|
228
|
+
|
|
229
|
+
def build_method(method_name, *args)
|
|
230
|
+
arguments = args.map do |argument|
|
|
231
|
+
if argument.is_a?(String)
|
|
232
|
+
argument = "'#{argument}'"
|
|
233
|
+
else
|
|
234
|
+
argument = argument.inspect
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
"#{replace_method(method_name)}(#{arguments.join(',')})"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
private :build_method
|
|
241
|
+
|
|
242
|
+
def generate_ruby_code(element, method_name, *args)
|
|
243
|
+
# needs to be done like this to avoid segfault on ruby 1.9.3
|
|
244
|
+
tag_name = @specifiers[:tag_name].join("' << '")
|
|
245
|
+
element = "#{self.class}.new(#{@page_container.attach_command}, :tag_name => Array.new << '#{tag_name}', :unique_number => #{unique_number})"
|
|
246
|
+
method = build_method(method_name, *args)
|
|
247
|
+
ruby_code = "$:.unshift(#{$LOAD_PATH.map {|p| "'#{p}'" }.join(").unshift(")});" <<
|
|
248
|
+
"require '#{File.expand_path(File.dirname(__FILE__))}/core';#{element}.#{method};"
|
|
249
|
+
ruby_code
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
private :generate_ruby_code
|
|
253
|
+
|
|
254
|
+
def spawned_no_wait_command(command)
|
|
255
|
+
command = "-e #{command.inspect}"
|
|
256
|
+
unless $DEBUG
|
|
257
|
+
"start rubyw #{command}"
|
|
258
|
+
else
|
|
259
|
+
puts "#no_wait command:"
|
|
260
|
+
command = "ruby #{command}"
|
|
261
|
+
puts command
|
|
262
|
+
command
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
private :spawned_no_wait_command
|
|
267
|
+
|
|
268
|
+
def click!
|
|
269
|
+
perform_action do
|
|
270
|
+
# Not sure why but in IE9 Document mode, passing a parameter
|
|
271
|
+
# to click seems to work. Firing the onClick event breaks other tests
|
|
272
|
+
# so this seems to be the safest change and also works fine in IE8
|
|
273
|
+
ole_object.click(0)
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Flash the element the specified number of times.
|
|
278
|
+
# Defaults to 10 flashes.
|
|
279
|
+
def flash number=10
|
|
280
|
+
assert_exists
|
|
281
|
+
number.times do
|
|
282
|
+
highlight(:set)
|
|
283
|
+
sleep 0.05
|
|
284
|
+
highlight(:clear)
|
|
285
|
+
sleep 0.05
|
|
286
|
+
end
|
|
287
|
+
nil
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Executes a user defined "fireEvent" for objects with JavaScript events tied to them such as DHTML menus.
|
|
291
|
+
# usage: allows a generic way to fire javascript events on page objects such as "onMouseOver", "onClick", etc.
|
|
292
|
+
# raises: UnknownObjectException if the object is not found
|
|
293
|
+
# ObjectDisabledException if the object is currently disabled
|
|
294
|
+
def fire_event(event)
|
|
295
|
+
perform_action {dispatch_event(event); @container.wait}
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def dispatch_event(event)
|
|
299
|
+
assert_exists
|
|
300
|
+
|
|
301
|
+
if IE.version_parts.first.to_i >= 9 && container.page_container.document.documentMode.to_i >= 9
|
|
302
|
+
ole_object.dispatchEvent(create_event(event))
|
|
303
|
+
else
|
|
304
|
+
ole_object.fireEvent(event)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def create_event(event)
|
|
309
|
+
event =~ /on(.*)/i
|
|
310
|
+
event = $1 if $1
|
|
311
|
+
event.downcase!
|
|
312
|
+
# See http://www.howtocreate.co.uk/tutorials/javascript/domevents
|
|
313
|
+
case event
|
|
314
|
+
when 'abort', 'blur', 'change', 'error', 'focus', 'load',
|
|
315
|
+
'reset', 'resize', 'scroll', 'select', 'submit', 'unload'
|
|
316
|
+
event_name = :initEvent
|
|
317
|
+
event_type = 'HTMLEvents'
|
|
318
|
+
event_args = [event, true, true]
|
|
319
|
+
when 'select'
|
|
320
|
+
event_name = :initUIEvent
|
|
321
|
+
event_type = 'UIEvent'
|
|
322
|
+
event_args = [event, true, true, @container.page_container.document.parentWindow.window,0]
|
|
323
|
+
when 'keydown', 'keypress', 'keyup'
|
|
324
|
+
event_name = :initKeyboardEvent
|
|
325
|
+
event_type = 'KeyboardEvent'
|
|
326
|
+
# 'type', bubbles, cancelable, windowObject, ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode
|
|
327
|
+
event_args = [event, true, true, @container.page_container.document.parentWindow.window, false, false, false, false, 0, 0]
|
|
328
|
+
when 'click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup',
|
|
329
|
+
'contextmenu', 'drag', 'dragstart', 'dragenter', 'dragover', 'dragleave', 'dragend', 'drop', 'selectstart'
|
|
330
|
+
event_name = :initMouseEvent
|
|
331
|
+
event_type = 'MouseEvents'
|
|
332
|
+
# 'type', bubbles, cancelable, windowObject, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget
|
|
333
|
+
event_args = [event, true, true, @container.page_container.document.parentWindow.window, 1, 0, 0, 0, 0, false, false, false, false, 0, @container.page_container.document]
|
|
334
|
+
else
|
|
335
|
+
raise UnhandledEventException, "Don't know how to trigger event '#{event}'"
|
|
336
|
+
end
|
|
337
|
+
event = @container.page_container.document.createEvent(event_type)
|
|
338
|
+
event.send event_name, *event_args
|
|
339
|
+
event
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# This method sets focus on the active element.
|
|
343
|
+
# raises: UnknownObjectException if the object is not found
|
|
344
|
+
# ObjectDisabledException if the object is currently disabled
|
|
345
|
+
def focus
|
|
346
|
+
assert_exists
|
|
347
|
+
assert_enabled
|
|
348
|
+
@page_container.focus
|
|
349
|
+
ole_object.focus(0)
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def focused?
|
|
353
|
+
assert_exists
|
|
354
|
+
assert_enabled
|
|
355
|
+
@page_container.document.activeElement.uniqueNumber == unique_number
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# Returns whether this element actually exists.
|
|
359
|
+
def exists?
|
|
360
|
+
begin
|
|
361
|
+
locate
|
|
362
|
+
rescue WIN32OLERuntimeError, UnknownObjectException
|
|
363
|
+
@o = nil
|
|
364
|
+
end
|
|
365
|
+
!!@o
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
alias :exist? :exists?
|
|
369
|
+
|
|
370
|
+
# Returns true if the element is enabled, false if it isn't.
|
|
371
|
+
# raises: UnknownObjectException if the object is not found
|
|
372
|
+
def enabled?
|
|
373
|
+
assert_exists
|
|
374
|
+
!disabled?
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def disabled?
|
|
378
|
+
assert_exists
|
|
379
|
+
false
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# If any parent element isn't visible then we cannot write to the
|
|
383
|
+
# element. The only realiable way to determine this is to iterate
|
|
384
|
+
# up the DOM element tree checking every element to make sure it's
|
|
385
|
+
# visible.
|
|
386
|
+
def visible?
|
|
387
|
+
# Now iterate up the DOM element tree and return false if any
|
|
388
|
+
# parent element isn't visible
|
|
389
|
+
assert_exists
|
|
390
|
+
object = @o
|
|
391
|
+
while object
|
|
392
|
+
begin
|
|
393
|
+
if object.currentstyle.invoke('visibility') =~ /^hidden$/i
|
|
394
|
+
return false
|
|
395
|
+
end
|
|
396
|
+
if object.currentstyle.invoke('display') =~ /^none$/i
|
|
397
|
+
return false
|
|
398
|
+
end
|
|
399
|
+
rescue WIN32OLERuntimeError
|
|
400
|
+
end
|
|
401
|
+
object = object.parentElement
|
|
402
|
+
end
|
|
403
|
+
true
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Get attribute value for any attribute of the element.
|
|
407
|
+
# Returns null if attribute doesn't exist.
|
|
408
|
+
def attribute_value(attribute_name)
|
|
409
|
+
assert_exists
|
|
410
|
+
ole_object.getAttribute(attribute_name)
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def perform_action
|
|
414
|
+
assert_exists
|
|
415
|
+
assert_enabled
|
|
416
|
+
highlight(:set)
|
|
417
|
+
yield
|
|
418
|
+
highlight(:clear)
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
private :perform_action
|
|
422
|
+
|
|
423
|
+
def method_missing(method_name, *args, &block)
|
|
424
|
+
meth = method_name.to_s
|
|
425
|
+
if meth =~ /(.*)_no_wait/ && self.respond_to?($1)
|
|
426
|
+
perform_action do
|
|
427
|
+
ruby_code = generate_ruby_code(self, $1, *args)
|
|
428
|
+
system(spawned_no_wait_command(ruby_code))
|
|
429
|
+
end
|
|
430
|
+
elsif meth =~ /^data_(.*)/
|
|
431
|
+
self.send(:attribute_value, meth.gsub("_", "-")) || ''
|
|
432
|
+
else
|
|
433
|
+
super
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
end
|
|
438
|
+
end
|